From c62ce3eecb01bda070129143a170ceb63e0f23b9 Mon Sep 17 00:00:00 2001 From: Koushik Das Date: Tue, 24 Mar 2015 09:21:42 +0530 Subject: [PATCH] volume-upload: Templates in uploaded error state are also accounted in resource limits which leads to failure during template upload even though there aren't any active ones Fixed the storage GC thread to clean up templates in error/abandoned states. --- .../com/cloud/storage/StorageManagerImpl.java | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index fb51ff5ce9a..91e4047d2fa 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -70,6 +70,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; @@ -150,6 +151,7 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.listener.StoragePoolMonitor; import com.cloud.storage.listener.VolumeStateListener; import com.cloud.template.TemplateManager; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.ResourceLimitService; @@ -1082,7 +1084,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C } } - // destroy uploaded volumes in UploadAbandoned/UploadError state + // destroy uploaded volumes in abandoned/error state List volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned); for (VolumeDataStoreVO volumeDataStore : volumeDataStores) { VolumeVO volume = _volumeDao.findById(volumeDataStore.getVolumeId()); @@ -1111,7 +1113,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C if (volOnSecondary != null) { s_logger.info("Expunging volume " + volume.getUuid() + " uploaded using HTTP POST from secondary data store"); AsyncCallFuture future = volService.expungeVolumeAsync(volOnSecondary); - future.get(); + VolumeApiResult result = future.get(); + if (!result.isSuccess()) { + s_logger.warn("Failed to expunge volume " + volume.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult()); + } } } } @@ -1119,6 +1124,55 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid() + ". Error details: " + th.getMessage()); } } + + // destroy uploaded templates in abandoned/error state + List templateDataStores = _templateStoreDao.listByTemplateState(VirtualMachineTemplate.State.UploadError, VirtualMachineTemplate.State.UploadAbandoned); + for (TemplateDataStoreVO templateDataStore : templateDataStores) { + VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId()); + if (template == null) { + s_logger.warn("Uploaded template with id " + templateDataStore.getTemplateId() + " not found, so cannot be destroyed"); + continue; + } + try { + DataStore dataStore = _dataStoreMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image); + EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl()); + if (ep == null) { + s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded template " + template.getUuid()); + continue; + } + Host host = _hostDao.findById(ep.getId()); + if (host != null && host.getManagementServerId() != null) { + if (_serverId == host.getManagementServerId().longValue()) { + AsyncCallFuture future = _imageSrv.deleteTemplateAsync(tmplFactory.getTemplate(template.getId(), dataStore)); + TemplateApiResult result = future.get(); + if (!result.isSuccess()) { + s_logger.warn("Failed to delete template " + template.getUuid() + " from the image store " + dataStore.getName() + " due to: " + result.getResult()); + continue; + } + // remove from template_zone_ref + List templateZones = _vmTemplateZoneDao.listByZoneTemplate(((ImageStoreEntity)dataStore).getDataCenterId(), template.getId()); + if (templateZones != null) { + for (VMTemplateZoneVO templateZone : templateZones) { + _vmTemplateZoneDao.remove(templateZone.getId()); + } + } + // mark all the occurrences of this template in the given store as destroyed + _templateStoreDao.removeByTemplateStore(template.getId(), dataStore.getId()); + // find all eligible image stores for this template + List imageStores = _tmpltMgr.getImageStoreByTemplate(template.getId(), null); + if (imageStores == null || imageStores.size() == 0) { + template.setState(VirtualMachineTemplate.State.Inactive); + _templateDao.update(template.getId(), template); + + // decrement template resource count + _resourceLimitMgr.decrementResourceCount(template.getAccountId(), ResourceType.template); + } + } + } + } catch (Throwable th) { + s_logger.warn("Unable to destroy uploaded template " + template.getUuid() + ". Error details: " + th.getMessage()); + } + } } finally { scanLock.unlock(); }