volume-upload: Volume resource count is incremented even for failed and abandoned volumes

Added logic to clean up abandoned and failed volume uploads. This is done as part of storage GC.
This commit is contained in:
Koushik Das 2015-03-11 16:24:03 +05:30
parent db7964fb11
commit 1dae3a4a13

View File

@ -43,7 +43,6 @@ import javax.naming.ConfigurationException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd; import org.apache.cloudstack.api.command.admin.storage.CancelPrimaryStorageMaintenanceCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd; import org.apache.cloudstack.api.command.admin.storage.CreateSecondaryStagingStoreCmd;
import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd; import org.apache.cloudstack.api.command.admin.storage.CreateStoragePoolCmd;
@ -59,6 +58,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener;
@ -71,6 +71,7 @@ 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.TemplateDataFactory;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; 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; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService;
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@ -108,6 +109,7 @@ import com.cloud.cluster.ClusterManagerListener;
import com.cloud.cluster.ManagementServerHost; import com.cloud.cluster.ManagementServerHost;
import com.cloud.configuration.Config; import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterDao;
@ -150,6 +152,7 @@ import com.cloud.storage.listener.VolumeStateListener;
import com.cloud.template.TemplateManager; import com.cloud.template.TemplateManager;
import com.cloud.user.Account; import com.cloud.user.Account;
import com.cloud.user.AccountManager; import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserDao;
import com.cloud.utils.DateUtil; import com.cloud.utils.DateUtil;
import com.cloud.utils.NumbersUtil; import com.cloud.utils.NumbersUtil;
@ -193,6 +196,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
@Inject @Inject
protected VolumeDao _volsDao; protected VolumeDao _volsDao;
@Inject @Inject
private VolumeDataStoreDao _volumeDataStoreDao;
@Inject
protected HostDao _hostDao; protected HostDao _hostDao;
@Inject @Inject
protected SnapshotDao _snapshotDao; protected SnapshotDao _snapshotDao;
@ -245,10 +250,6 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
@Inject @Inject
ManagementServer _msServer; ManagementServer _msServer;
@Inject @Inject
DataStoreManager dataStoreMgr;
@Inject
DataStoreProviderManager dataStoreProviderMgr;
@Inject
VolumeService volService; VolumeService volService;
@Inject @Inject
VolumeDataFactory volFactory; VolumeDataFactory volFactory;
@ -266,6 +267,8 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
private TemplateService _imageSrv; private TemplateService _imageSrv;
@Inject @Inject
EndPointSelector _epSelector; EndPointSelector _epSelector;
@Inject
ResourceLimitService _resourceLimitMgr;
protected List<StoragePoolDiscoverer> _discoverers; protected List<StoragePoolDiscoverer> _discoverers;
@ -563,7 +566,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
} }
DataStoreProvider provider = dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider(); DataStoreProvider provider = _dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider();
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
if (pool == null) { if (pool == null) {
Map<String, Object> params = new HashMap<String, Object>(); Map<String, Object> params = new HashMap<String, Object>();
@ -580,7 +583,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
store = lifeCycle.initialize(params); store = lifeCycle.initialize(params);
} else { } else {
store = dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); store = _dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
} }
HostScope scope = new HostScope(host.getId(), host.getClusterId(), host.getDataCenterId()); HostScope scope = new HostScope(host.getId(), host.getClusterId(), host.getDataCenterId());
@ -590,17 +593,17 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
throw new ConnectionException(true, "Unable to setup the local storage pool for " + host, e); throw new ConnectionException(true, "Unable to setup the local storage pool for " + host, e);
} }
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); return _dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
} }
@Override @Override
public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException, public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws ResourceInUseException, IllegalArgumentException, UnknownHostException,
ResourceUnavailableException { ResourceUnavailableException {
String providerName = cmd.getStorageProviderName(); String providerName = cmd.getStorageProviderName();
DataStoreProvider storeProvider = dataStoreProviderMgr.getDataStoreProvider(providerName); DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(providerName);
if (storeProvider == null) { if (storeProvider == null) {
storeProvider = dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider(); storeProvider = _dataStoreProviderMgr.getDefaultPrimaryDataStoreProvider();
if (storeProvider == null) { if (storeProvider == null) {
throw new InvalidParameterValueException("can't find storage provider: " + providerName); throw new InvalidParameterValueException("can't find storage provider: " + providerName);
} }
@ -695,7 +698,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
throw new CloudRuntimeException("Failed to add data store: "+e.getMessage(), e); throw new CloudRuntimeException("Failed to add data store: "+e.getMessage(), e);
} }
return (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary); return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
} }
private Map<String, String> extractApiParamAsMap(Map ds) { private Map<String, String> extractApiParamAsMap(Map ds) {
@ -786,7 +789,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
if (updatedCapacityBytes != null || updatedCapacityIops != null) { if (updatedCapacityBytes != null || updatedCapacityIops != null) {
StoragePoolVO storagePool = _storagePoolDao.findById(id); StoragePoolVO storagePool = _storagePoolDao.findById(id);
DataStoreProvider dataStoreProvider = dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName()); DataStoreProvider dataStoreProvider = _dataStoreProviderMgr.getDataStoreProvider(storagePool.getStorageProviderName());
DataStoreLifeCycle dataStoreLifeCycle = dataStoreProvider.getDataStoreLifeCycle(); DataStoreLifeCycle dataStoreLifeCycle = dataStoreProvider.getDataStoreLifeCycle();
if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) { if (dataStoreLifeCycle instanceof PrimaryDataStoreLifeCycle) {
@ -811,7 +814,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
_storagePoolDao.updateCapacityIops(id, capacityIops); _storagePoolDao.updateCapacityIops(id, capacityIops);
} }
return (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary); return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
} }
@Override @Override
@ -875,19 +878,19 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
_storagePoolDao.releaseFromLockTable(lock.getId()); _storagePoolDao.releaseFromLockTable(lock.getId());
s_logger.trace("Released lock for storage pool " + id); s_logger.trace("Released lock for storage pool " + id);
DataStoreProvider storeProvider = dataStoreProviderMgr.getDataStoreProvider(sPool.getStorageProviderName()); DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(sPool.getStorageProviderName());
DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle();
DataStore store = dataStoreMgr.getDataStore(sPool.getId(), DataStoreRole.Primary); DataStore store = _dataStoreMgr.getDataStore(sPool.getId(), DataStoreRole.Primary);
return lifeCycle.deleteDataStore(store); return lifeCycle.deleteDataStore(store);
} }
@Override @Override
public void connectHostToSharedPool(long hostId, long poolId) throws StorageUnavailableException { public void connectHostToSharedPool(long hostId, long poolId) throws StorageUnavailableException {
StoragePool pool = (StoragePool)dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); StoragePool pool = (StoragePool)_dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary);
assert (pool.isShared()) : "Now, did you actually read the name of this method?"; assert (pool.isShared()) : "Now, did you actually read the name of this method?";
s_logger.debug("Adding pool " + pool.getName() + " to host " + hostId); s_logger.debug("Adding pool " + pool.getName() + " to host " + hostId);
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName());
HypervisorHostListener listener = hostListeners.get(provider.getName()); HypervisorHostListener listener = hostListeners.get(provider.getName());
listener.hostConnect(hostId, pool.getId()); listener.hostConnect(hostId, pool.getId());
} }
@ -1059,11 +1062,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed(); List<VolumeVO> vols = _volsDao.listVolumesToBeDestroyed();
for (VolumeVO vol : vols) { for (VolumeVO vol : vols) {
try { try {
volService.expungeVolumeAsync(volFactory.getVolume(vol.getId())); volService.expungeVolumeAsync(volFactory.getVolume(vol.getId()));
} catch (Exception e) { } catch (Exception e) {
s_logger.warn("Unable to destroy " + vol.getId(), e); s_logger.warn("Unable to destroy volume " + vol.getUuid(), e);
} }
} }
@ -1077,10 +1078,47 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
} }
_snapshotDao.expunge(snapshotVO.getId()); _snapshotDao.expunge(snapshotVO.getId());
} catch (Exception e) { } catch (Exception e) {
s_logger.warn("Unable to destroy " + snapshotVO.getId(), e); s_logger.warn("Unable to destroy snapshot " + snapshotVO.getUuid(), e);
} }
} }
// destroy uploaded volumes in UploadAbandoned/UploadError state
List<VolumeDataStoreVO> volumeDataStores = _volumeDataStoreDao.listByVolumeState(Volume.State.UploadError, Volume.State.UploadAbandoned);
for (VolumeDataStoreVO volumeDataStore : volumeDataStores) {
VolumeVO volume = _volumeDao.findById(volumeDataStore.getVolumeId());
if (volume == null) {
s_logger.warn("Uploaded volume with id " + volumeDataStore.getVolumeId() + " not found, so cannot be destroyed");
continue;
}
try {
DataStore dataStore = _dataStoreMgr.getDataStore(volumeDataStore.getDataStoreId(), DataStoreRole.Image);
EndPoint ep = _epSelector.select(dataStore, volumeDataStore.getExtractUrl());
if (ep == null) {
s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName() + ", cannot destroy uploaded volume " + volume.getUuid());
continue;
}
Host host = _hostDao.findById(ep.getId());
if (host != null && host.getManagementServerId() != null) {
if (_serverId == host.getManagementServerId().longValue()) {
if (!volService.destroyVolume(volume.getId())) {
s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid());
continue;
}
// decrement volume resource count
_resourceLimitMgr.decrementResourceCount(volume.getAccountId(), ResourceType.volume, volume.isDisplayVolume());
// expunge volume from secondary if volume is on image store
VolumeInfo volOnSecondary = volFactory.getVolume(volume.getId(), DataStoreRole.Image);
if (volOnSecondary != null) {
s_logger.info("Expunging volume " + volume.getUuid() + " uploaded using HTTP POST from secondary data store");
AsyncCallFuture<VolumeApiResult> future = volService.expungeVolumeAsync(volOnSecondary);
future.get();
}
}
}
} catch (Throwable th) {
s_logger.warn("Unable to destroy uploaded volume " + volume.getUuid() + ". Error details: " + th.getMessage());
}
}
} finally { } finally {
scanLock.unlock(); scanLock.unlock();
} }
@ -1139,7 +1177,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
// so here we don't need to issue DeleteCommand to resource anymore, only need to remove db entry. // so here we don't need to issue DeleteCommand to resource anymore, only need to remove db entry.
try { try {
// Cleanup templates in template_store_ref // Cleanup templates in template_store_ref
List<DataStore> imageStores = dataStoreMgr.getImageStoresByScope(new ZoneScope(null)); List<DataStore> imageStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(null));
for (DataStore store : imageStores) { for (DataStore store : imageStores) {
try { try {
long storeId = store.getId(); long storeId = store.getId();
@ -1236,12 +1274,12 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
primaryStorage.getStatus().toString()); primaryStorage.getStatus().toString());
} }
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName());
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
DataStore store = dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); DataStore store = _dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary);
lifeCycle.maintain(store); lifeCycle.maintain(store);
return (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary);
} }
@Override @Override
@ -1263,12 +1301,12 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
primaryStorage.getStatus().toString(), primaryStorageId); primaryStorage.getStatus().toString(), primaryStorageId);
} }
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName()); DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(primaryStorage.getStorageProviderName());
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
DataStore store = dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); DataStore store = _dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary);
lifeCycle.cancelMaintain(store); lifeCycle.cancelMaintain(store);
return (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary); return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(primaryStorage.getId(), DataStoreRole.Primary);
} }
@ -1396,7 +1434,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
@Override @Override
public PrimaryDataStoreInfo getStoragePool(long id) { public PrimaryDataStoreInfo getStoragePool(long id) {
return (PrimaryDataStoreInfo)dataStoreMgr.getDataStore(id, DataStoreRole.Primary); return (PrimaryDataStoreInfo)_dataStoreMgr.getDataStore(id, DataStoreRole.Primary);
} }
@Override @Override
@ -1784,9 +1822,9 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
_accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), store.getDataCenterId()); _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), store.getDataCenterId());
DataStoreProvider provider = dataStoreProviderMgr.getDataStoreProvider(store.getProviderName()); DataStoreProvider provider = _dataStoreProviderMgr.getDataStoreProvider(store.getProviderName());
DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle(); DataStoreLifeCycle lifeCycle = provider.getDataStoreLifeCycle();
DataStore secStore = dataStoreMgr.getDataStore(storeId, DataStoreRole.Image); DataStore secStore = _dataStoreMgr.getDataStore(storeId, DataStoreRole.Image);
lifeCycle.migrateToObjectStore(secStore); lifeCycle.migrateToObjectStore(secStore);
// update store_role in template_store_ref and snapshot_store_ref to ImageCache // update store_role in template_store_ref and snapshot_store_ref to ImageCache
_templateStoreDao.updateStoreRoleToCachce(storeId); _templateStoreDao.updateStoreRoleToCachce(storeId);