Updated Branches: refs/heads/master 494ea5052 -> 3937a7b5a
CLOUDSTACK-4400:[object_store_refactor] Three entries for one template in template_store_ref when MS was restarting during template download. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/3937a7b5 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/3937a7b5 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/3937a7b5 Branch: refs/heads/master Commit: 3937a7b5a554b0c6816cd37afe4e482bff48ec55 Parents: 494ea50 Author: Min Chen <min.c...@citrix.com> Authored: Mon Aug 19 15:00:24 2013 -0700 Committer: Min Chen <min.c...@citrix.com> Committed: Mon Aug 19 15:01:57 2013 -0700 ---------------------------------------------------------------------- .../storage/image/TemplateServiceImpl.java | 341 ++++++++++--------- .../storage/volume/VolumeServiceImpl.java | 228 +++++++------ 2 files changed, 304 insertions(+), 265 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3937a7b5/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java index 7d9a740..b8f8f4f 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -87,6 +87,7 @@ import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.ResourceLimitService; import com.cloud.utils.UriUtils; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.exception.CloudRuntimeException; @Component @@ -253,185 +254,203 @@ public class TemplateServiceImpl implements TemplateService { return; } long storeId = store.getId(); - Long zoneId = store.getScope().getScopeId(); - Map<String, TemplateProp> templateInfos = listTemplate(store); - if (templateInfos == null) { - return; - } - - Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>(); - List<VMTemplateVO> allTemplates = null; - if (zoneId == null) { - // region wide store - allTemplates = _templateDao.listAllActive(); - } else { - // zone wide store - allTemplates = _templateDao.listAllInZone(zoneId); - } - List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); - List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); + // add lock to make template sync for a data store only be done once + String lockString = "templatesync.storeId:" + storeId; + GlobalLock syncLock = GlobalLock.getInternLock(lockString); + try { + if (syncLock.lock(3)) { + try{ + Long zoneId = store.getScope().getScopeId(); - if (rtngTmplts != null) { - for (VMTemplateVO rtngTmplt : rtngTmplts) { - if (!allTemplates.contains(rtngTmplt)) { - allTemplates.add(rtngTmplt); - } - } - } + Map<String, TemplateProp> templateInfos = listTemplate(store); + if (templateInfos == null) { + return; + } - if (defaultBuiltin != null) { - for (VMTemplateVO builtinTmplt : defaultBuiltin) { - if (!allTemplates.contains(builtinTmplt)) { - allTemplates.add(builtinTmplt); - } - } - } + Set<VMTemplateVO> toBeDownloaded = new HashSet<VMTemplateVO>(); + List<VMTemplateVO> allTemplates = null; + if (zoneId == null) { + // region wide store + allTemplates = _templateDao.listAllActive(); + } else { + // zone wide store + allTemplates = _templateDao.listAllInZone(zoneId); + } + List<VMTemplateVO> rtngTmplts = _templateDao.listAllSystemVMTemplates(); + List<VMTemplateVO> defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); - toBeDownloaded.addAll(allTemplates); + if (rtngTmplts != null) { + for (VMTemplateVO rtngTmplt : rtngTmplts) { + if (!allTemplates.contains(rtngTmplt)) { + allTemplates.add(rtngTmplt); + } + } + } - for (VMTemplateVO tmplt : allTemplates) { - String uniqueName = tmplt.getUniqueName(); - TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); - if (templateInfos.containsKey(uniqueName)) { - TemplateProp tmpltInfo = templateInfos.remove(uniqueName); - toBeDownloaded.remove(tmplt); - if (tmpltStore != null) { - s_logger.info("Template Sync found " + uniqueName + " already in the image store"); - if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { - tmpltStore.setErrorString(""); + if (defaultBuiltin != null) { + for (VMTemplateVO builtinTmplt : defaultBuiltin) { + if (!allTemplates.contains(builtinTmplt)) { + allTemplates.add(builtinTmplt); + } + } } - if (tmpltInfo.isCorrupted()) { - tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() - + " is corrupted on secondary storage " + tmpltStore.getId(); - tmpltStore.setErrorString(msg); - s_logger.info("msg"); - if (tmplt.getUrl() == null) { - msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() - + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); - s_logger.warn(msg); + + toBeDownloaded.addAll(allTemplates); + + for (VMTemplateVO tmplt : allTemplates) { + String uniqueName = tmplt.getUniqueName(); + TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); + if (templateInfos.containsKey(uniqueName)) { + TemplateProp tmpltInfo = templateInfos.remove(uniqueName); + toBeDownloaded.remove(tmplt); + if (tmpltStore != null) { + s_logger.info("Template Sync found " + uniqueName + " already in the image store"); + if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { + tmpltStore.setErrorString(""); + } + if (tmpltInfo.isCorrupted()) { + tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + + " is corrupted on secondary storage " + tmpltStore.getId(); + tmpltStore.setErrorString(msg); + s_logger.info("msg"); + if (tmplt.getUrl() == null) { + msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); + s_logger.warn(msg); + } else { + s_logger.info("Removing template_store_ref entry for corrupted template " + tmplt.getName()); + _vmTemplateStoreDao.remove(tmpltStore.getId()); + toBeDownloaded.add(tmplt); + } + + } else { + tmpltStore.setDownloadPercent(100); + tmpltStore.setDownloadState(Status.DOWNLOADED); + tmpltStore.setState(ObjectInDataStoreStateMachine.State.Ready); + tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + tmpltStore.setLastUpdated(new Date()); + // update size in vm_template table + VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); + tmlpt.setSize(tmpltInfo.getSize()); + _templateDao.update(tmplt.getId(), tmlpt); + + // Skipping limit checks for SYSTEM Account and for the templates created from volumes or snapshots + // which already got checked and incremented during createTemplate API call. + if (tmpltInfo.getSize() > 0 && tmplt.getAccountId() != Account.ACCOUNT_ID_SYSTEM && tmplt.getUrl() != null) { + long accountId = tmplt.getAccountId(); + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), + com.cloud.configuration.Resource.ResourceType.secondary_storage, + tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, null, + e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId) + .getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage + .getOrdinal()); + } + } + } + _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); + } else { + tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, + null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + tmpltStore.setDataStoreRole(store.getRole()); + _vmTemplateStoreDao.persist(tmpltStore); + + // update size in vm_template table + VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); + tmlpt.setSize(tmpltInfo.getSize()); + _templateDao.update(tmplt.getId(), tmlpt); + associateTemplateToZone(tmplt.getId(), zoneId); + + + } } else { - s_logger.info("Removing template_store_ref entry for corrupted template " + tmplt.getName()); - _vmTemplateStoreDao.remove(tmpltStore.getId()); - toBeDownloaded.add(tmplt); + s_logger.info("Template Sync did not find " + uniqueName + " on image store " + storeId + ", may request download based on available hypervisor types"); + if (tmpltStore != null) { + s_logger.info("Removing leftover template " + uniqueName + " entry from template store table"); + // remove those leftover entries + _vmTemplateStoreDao.remove(tmpltStore.getId()); + } } + } - } else { - tmpltStore.setDownloadPercent(100); - tmpltStore.setDownloadState(Status.DOWNLOADED); - tmpltStore.setState(ObjectInDataStoreStateMachine.State.Ready); - tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); - tmpltStore.setSize(tmpltInfo.getSize()); - tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); - tmpltStore.setLastUpdated(new Date()); - // update size in vm_template table - VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); - tmlpt.setSize(tmpltInfo.getSize()); - _templateDao.update(tmplt.getId(), tmlpt); - - // Skipping limit checks for SYSTEM Account and for the templates created from volumes or snapshots - // which already got checked and incremented during createTemplate API call. - if (tmpltInfo.getSize() > 0 && tmplt.getAccountId() != Account.ACCOUNT_ID_SYSTEM && tmplt.getUrl() != null) { - long accountId = tmplt.getAccountId(); - try { - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, null, - e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId) - .getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage - .getOrdinal()); + if (toBeDownloaded.size() > 0) { + /* Only download templates whose hypervirsor type is in the zone */ + List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); + if (availHypers.isEmpty()) { + /* + * This is for cloudzone, local secondary storage resource + * started before cluster created + */ + availHypers.add(HypervisorType.KVM); + } + /* Baremetal need not to download any template */ + availHypers.remove(HypervisorType.BareMetal); + availHypers.add(HypervisorType.None); // bug 9809: resume ISO + // download. + for (VMTemplateVO tmplt : toBeDownloaded) { + if (tmplt.getUrl() == null) { // If url is null we can't + s_logger.info("Skip downloading template " + tmplt.getUniqueName() + " since no url is specified."); + continue; + } + + if (availHypers.contains(tmplt.getHypervisorType())) { + s_logger.info("Downloading template " + tmplt.getUniqueName() + " to image store " + + store.getName()); + associateTemplateToZone(tmplt.getId(), zoneId); + TemplateInfo tmpl = _templateFactory.getTemplate(tmplt.getId(), DataStoreRole.Image); + createTemplateAsync(tmpl, store, null); + } else { + s_logger.info("Skip downloading template " + tmplt.getUniqueName() + " since current data center does not have hypervisor " + + tmplt.getHypervisorType().toString()); } } } - _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); - } else { - tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, - null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); - tmpltStore.setSize(tmpltInfo.getSize()); - tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); - tmpltStore.setDataStoreRole(store.getRole()); - _vmTemplateStoreDao.persist(tmpltStore); - - // update size in vm_template table - VMTemplateVO tmlpt = _templateDao.findById(tmplt.getId()); - tmlpt.setSize(tmpltInfo.getSize()); - _templateDao.update(tmplt.getId(), tmlpt); - associateTemplateToZone(tmplt.getId(), zoneId); + for (String uniqueName : templateInfos.keySet()) { + TemplateProp tInfo = templateInfos.get(uniqueName); + if (_tmpltMgr.templateIsDeleteable(tInfo.getId())) { + // we cannot directly call deleteTemplateSync here to + // reuse delete logic since in this case, our db does not have + // this template at all. + TemplateObjectTO tmplTO = new TemplateObjectTO(); + tmplTO.setDataStore(store.getTO()); + tmplTO.setPath(tInfo.getInstallPath()); + tmplTO.setId(tInfo.getId()); + DeleteCommand dtCommand = new DeleteCommand(tmplTO); + EndPoint ep = _epSelector.select(store); + Answer answer = ep.sendMessage(dtCommand); + if (answer == null || !answer.getResult()) { + s_logger.info("Failed to deleted template at store: " + store.getName()); + + } else { + String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + + storeId; + s_logger.info(description); + } + } + } } - } else { - s_logger.info("Template Sync did not find " + uniqueName + " on image store " + storeId + ", may request download based on available hypervisor types"); - if (tmpltStore != null) { - s_logger.info("Removing leftover template " + uniqueName + " entry from template store table"); - // remove those leftover entries - _vmTemplateStoreDao.remove(tmpltStore.getId()); - } - } - } - - if (toBeDownloaded.size() > 0) { - /* Only download templates whose hypervirsor type is in the zone */ - List<HypervisorType> availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); - if (availHypers.isEmpty()) { - /* - * This is for cloudzone, local secondary storage resource - * started before cluster created - */ - availHypers.add(HypervisorType.KVM); - } - /* Baremetal need not to download any template */ - availHypers.remove(HypervisorType.BareMetal); - availHypers.add(HypervisorType.None); // bug 9809: resume ISO - // download. - for (VMTemplateVO tmplt : toBeDownloaded) { - if (tmplt.getUrl() == null) { // If url is null we can't - s_logger.info("Skip downloading template " + tmplt.getUniqueName() + " since no url is specified."); - continue; - } - - if (availHypers.contains(tmplt.getHypervisorType())) { - s_logger.info("Downloading template " + tmplt.getUniqueName() + " to image store " - + store.getName()); - associateTemplateToZone(tmplt.getId(), zoneId); - TemplateInfo tmpl = _templateFactory.getTemplate(tmplt.getId(), DataStoreRole.Image); - createTemplateAsync(tmpl, store, null); - } else { - s_logger.info("Skip downloading template " + tmplt.getUniqueName() + " since current data center does not have hypervisor " - + tmplt.getHypervisorType().toString()); + finally{ + syncLock.unlock(); } } - } - - for (String uniqueName : templateInfos.keySet()) { - TemplateProp tInfo = templateInfos.get(uniqueName); - if (_tmpltMgr.templateIsDeleteable(tInfo.getId())) { - // we cannot directly call deleteTemplateSync here to - // reuse delete logic since in this case, our db does not have - // this template at all. - TemplateObjectTO tmplTO = new TemplateObjectTO(); - tmplTO.setDataStore(store.getTO()); - tmplTO.setPath(tInfo.getInstallPath()); - tmplTO.setId(tInfo.getId()); - DeleteCommand dtCommand = new DeleteCommand(tmplTO); - EndPoint ep = _epSelector.select(store); - Answer answer = ep.sendMessage(dtCommand); - if (answer == null || !answer.getResult()) { - s_logger.info("Failed to deleted template at store: " + store.getName()); - - } else { - String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " - + storeId; - s_logger.info(description); - } - + else { + s_logger.info("Couldn't get global lock on " + lockString + ", another thread may be doing template sync on data store " + storeId + " now."); } + } finally { + syncLock.releaseRef(); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/3937a7b5/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 5600ac7..e8304dd 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -91,6 +91,7 @@ import com.cloud.user.AccountManager; import com.cloud.user.ResourceLimitService; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.DB; +import com.cloud.utils.db.GlobalLock; import com.cloud.utils.exception.CloudRuntimeException; @Component @@ -304,7 +305,7 @@ public class VolumeServiceImpl implements VolumeService { apiResult.setResult(result.getResult()); } } catch (Exception e) { - s_logger.debug("ignore delete volume status update failure, it will be picked up by storage clean up thread later", e); + s_logger.debug("ignore delete volume status update failure, it will be picked up by storage clean up thread later", e); } context.getFuture().complete(apiResult); return null; @@ -1100,124 +1101,143 @@ public class VolumeServiceImpl implements VolumeService { @Override public void handleVolumeSync(DataStore store) { if (store == null) { - s_logger.warn("Huh? ssHost is null"); + s_logger.warn("Huh? image store is null"); return; } long storeId = store.getId(); - Map<Long, TemplateProp> volumeInfos = listVolume(store); - if (volumeInfos == null) { - return; - } + // add lock to make template sync for a data store only be done once + String lockString = "volumesync.storeId:" + storeId; + GlobalLock syncLock = GlobalLock.getInternLock(lockString); + try { + if ( syncLock.lock(3)){ + try { + Map<Long, TemplateProp> volumeInfos = listVolume(store); + if (volumeInfos == null) { + return; + } - List<VolumeDataStoreVO> dbVolumes = _volumeStoreDao.listByStoreId(storeId); - List<VolumeDataStoreVO> toBeDownloaded = new ArrayList<VolumeDataStoreVO>(dbVolumes); - for (VolumeDataStoreVO volumeStore : dbVolumes) { - VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); - if (volume == null ){ - s_logger.warn("Volume_store_ref shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId - + ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted and mark it as destroyed"); - volumeStore.setDestroyed(true); - _volumeStoreDao.update(volumeStore.getId(), volumeStore); - continue; - } - // Exists then don't download - if (volumeInfos.containsKey(volume.getId())) { - TemplateProp volInfo = volumeInfos.remove(volume.getId()); - toBeDownloaded.remove(volumeStore); - s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table"); - if (volumeStore.getDownloadState() != Status.DOWNLOADED) { - volumeStore.setErrorString(""); - } - if (volInfo.isCorrupted()) { - volumeStore.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Volume " + volume.getUuid() + " is corrupted on image store "; - volumeStore.setErrorString(msg); - s_logger.info("msg"); - if (volumeStore.getDownloadUrl() == null) { - msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() - + "is corrupted, please check in image store: " + volumeStore.getDataStoreId(); - s_logger.warn(msg); - } else { - toBeDownloaded.add(volumeStore); + List<VolumeDataStoreVO> dbVolumes = _volumeStoreDao.listByStoreId(storeId); + List<VolumeDataStoreVO> toBeDownloaded = new ArrayList<VolumeDataStoreVO>(dbVolumes); + for (VolumeDataStoreVO volumeStore : dbVolumes) { + VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); + if (volume == null ){ + s_logger.warn("Volume_store_ref shows that volume " + volumeStore.getVolumeId() + " is on image store " + storeId + + ", but the volume is not found in volumes table, potentially some bugs in deleteVolume, so we just treat this volume to be deleted and mark it as destroyed"); + volumeStore.setDestroyed(true); + _volumeStoreDao.update(volumeStore.getId(), volumeStore); + continue; + } + // Exists then don't download + if (volumeInfos.containsKey(volume.getId())) { + TemplateProp volInfo = volumeInfos.remove(volume.getId()); + toBeDownloaded.remove(volumeStore); + s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table"); + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + volumeStore.setErrorString(""); + } + if (volInfo.isCorrupted()) { + volumeStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Volume " + volume.getUuid() + " is corrupted on image store "; + volumeStore.setErrorString(msg); + s_logger.info("msg"); + if (volumeStore.getDownloadUrl() == null) { + msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + + "is corrupted, please check in image store: " + volumeStore.getDataStoreId(); + s_logger.warn(msg); + } else { + s_logger.info("Removing volume_store_ref entry for corrupted volume " + volume.getName()); + _volumeStoreDao.remove(volumeStore.getId()); + toBeDownloaded.add(volumeStore); + } + + } else { // Put them in right status + volumeStore.setDownloadPercent(100); + volumeStore.setDownloadState(Status.DOWNLOADED); + volumeStore.setState(ObjectInDataStoreStateMachine.State.Ready); + volumeStore.setInstallPath(volInfo.getInstallPath()); + volumeStore.setSize(volInfo.getSize()); + volumeStore.setPhysicalSize(volInfo.getPhysicalSize()); + volumeStore.setLastUpdated(new Date()); + _volumeStoreDao.update(volumeStore.getId(), volumeStore); + + if (volume.getSize() == 0) { + // Set volume size in volumes table + volume.setSize(volInfo.getSize()); + _volumeDao.update(volumeStore.getVolumeId(), volume); + } + + if (volInfo.getSize() > 0) { + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), + com.cloud.configuration.Resource.ResourceType.secondary_storage, volInfo.getSize() + - volInfo.getPhysicalSize()); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, + volume.getDataCenterId(), volume.getPodId(), e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), + com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); + } + } + } + continue; + } + // Volume is not on secondary but we should download. + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId + + ", will request download to start/resume shortly"); + toBeDownloaded.add(volumeStore); + } } - } else { // Put them in right status - volumeStore.setDownloadPercent(100); - volumeStore.setDownloadState(Status.DOWNLOADED); - volumeStore.setInstallPath(volInfo.getInstallPath()); - volumeStore.setSize(volInfo.getSize()); - volumeStore.setPhysicalSize(volInfo.getPhysicalSize()); - volumeStore.setLastUpdated(new Date()); - _volumeStoreDao.update(volumeStore.getId(), volumeStore); - - if (volume.getSize() == 0) { - // Set volume size in volumes table - volume.setSize(volInfo.getSize()); - _volumeDao.update(volumeStore.getVolumeId(), volume); + // Download volumes which haven't been downloaded yet. + if (toBeDownloaded.size() > 0) { + for (VolumeDataStoreVO volumeHost : toBeDownloaded) { + if (volumeHost.getDownloadUrl() == null) { // If url is null we + s_logger.info("Skip downloading volume " + volumeHost.getVolumeId() + " since no download url is specified."); + continue; + } + s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + store.getName()); + // TODO: pass a callback later + VolumeInfo vol = volFactory.getVolume(volumeHost.getVolumeId()); + createVolumeAsync(vol, store); + } } - if (volInfo.getSize() > 0) { - try { - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), - com.cloud.configuration.Resource.ResourceType.secondary_storage, volInfo.getSize() - - volInfo.getPhysicalSize()); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(AlertManager.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, - volume.getDataCenterId(), volume.getPodId(), e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); + // Delete volumes which are not present on DB. + for (Long uniqueName : volumeInfos.keySet()) { + TemplateProp tInfo = volumeInfos.get(uniqueName); + + //we cannot directly call expungeVolumeAsync here to + // reuse delete logic since in this case, our db does not have + // this template at all. + VolumeObjectTO tmplTO = new VolumeObjectTO(); + tmplTO.setDataStore(store.getTO()); + tmplTO.setPath(tInfo.getInstallPath()); + tmplTO.setId(tInfo.getId()); + DeleteCommand dtCommand = new DeleteCommand(tmplTO); + EndPoint ep = _epSelector.select(store); + Answer answer = ep.sendMessage(dtCommand); + if (answer == null || !answer.getResult()) { + s_logger.info("Failed to deleted volume at store: " + store.getName()); + + } else { + String description = "Deleted volume " + tInfo.getTemplateName() + " on secondary storage " + storeId; + s_logger.info(description); } } } - continue; - } - // Volume is not on secondary but we should download. - if (volumeStore.getDownloadState() != Status.DOWNLOADED) { - s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId - + ", will request download to start/resume shortly"); - toBeDownloaded.add(volumeStore); - } - } - - // Download volumes which haven't been downloaded yet. - if (toBeDownloaded.size() > 0) { - for (VolumeDataStoreVO volumeHost : toBeDownloaded) { - if (volumeHost.getDownloadUrl() == null) { // If url is null we - // can't initiate the - // download - continue; + finally{ + syncLock.unlock(); } - s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + store.getName()); - // TODO: pass a callback later - VolumeInfo vol = volFactory.getVolume(volumeHost.getVolumeId()); - createVolumeAsync(vol, store); } - } - - // Delete volumes which are not present on DB. - for (Long uniqueName : volumeInfos.keySet()) { - TemplateProp tInfo = volumeInfos.get(uniqueName); - - //we cannot directly call expungeVolumeAsync here to - // reuse delete logic since in this case, our db does not have - // this template at all. - VolumeObjectTO tmplTO = new VolumeObjectTO(); - tmplTO.setDataStore(store.getTO()); - tmplTO.setPath(tInfo.getInstallPath()); - tmplTO.setId(tInfo.getId()); - DeleteCommand dtCommand = new DeleteCommand(tmplTO); - EndPoint ep = _epSelector.select(store); - Answer answer = ep.sendMessage(dtCommand); - if (answer == null || !answer.getResult()) { - s_logger.info("Failed to deleted volume at store: " + store.getName()); - - } else { - String description = "Deleted volume " + tInfo.getTemplateName() + " on secondary storage " + storeId; - s_logger.info(description); + else { + s_logger.info("Couldn't get global lock on " + lockString + ", another thread may be doing volume sync on data store " + storeId + " now."); } + } finally { + syncLock.releaseRef(); } }