}
long storeId = store.getId();
// 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 {
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);
}
}
// 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);
}
}
// 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);
}
}
}
finally{
syncLock.unlock();
}
}
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();
}
}