CLOUDSTACK-8386: CS is returning sec. storage even if it is full and there are other sec. storage with free space.

This commit is contained in:
Sanjay Tripathi 2015-04-13 10:56:46 +05:30
parent 8f4abbc7bd
commit 30604e973a
6 changed files with 54 additions and 19 deletions

View File

@ -18,7 +18,6 @@
*/ */
package org.apache.cloudstack.storage.cache.allocator; package org.apache.cloudstack.storage.cache.allocator;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -33,7 +32,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import com.cloud.server.StatsCollector;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
@Component @Component
@ -43,6 +44,10 @@ public class StorageCacheRandomAllocator implements StorageCacheAllocator {
DataStoreManager dataStoreMgr; DataStoreManager dataStoreMgr;
@Inject @Inject
ObjectInDataStoreManager objectInStoreMgr; ObjectInDataStoreManager objectInStoreMgr;
@Inject
ImageStoreProviderManager imageStoreMgr;
@Inject
StatsCollector statsCollector;
@Override @Override
public DataStore getCacheStore(Scope scope) { public DataStore getCacheStore(Scope scope) {
@ -57,8 +62,7 @@ public class StorageCacheRandomAllocator implements StorageCacheAllocator {
return null; return null;
} }
Collections.shuffle(cacheStores); return imageStoreMgr.getImageStore(cacheStores);
return cacheStores.get(0);
} }
@Override @Override
@ -78,18 +82,12 @@ public class StorageCacheRandomAllocator implements StorageCacheAllocator {
if (cacheStores.size() > 1) { if (cacheStores.size() > 1) {
for (DataStore store : cacheStores) { for (DataStore store : cacheStores) {
DataObjectInStore obj = objectInStoreMgr.findObject(data, store); DataObjectInStore obj = objectInStoreMgr.findObject(data, store);
if (obj != null && obj.getState() == ObjectInDataStoreStateMachine.State.Ready) { if (obj != null && obj.getState() == ObjectInDataStoreStateMachine.State.Ready && statsCollector.imageStoreHasEnoughCapacity(store)) {
s_logger.debug("pick the cache store " + store.getId() + " where data is already there"); s_logger.debug("pick the cache store " + store.getId() + " where data is already there");
return store; return store;
} }
} }
// otherwise, just random pick one
Collections.shuffle(cacheStores);
} }
return cacheStores.get(0); return imageStoreMgr.getImageStore(cacheStores);
} }
} }

View File

@ -19,7 +19,9 @@
package org.apache.cloudstack.storage.image.manager; package org.apache.cloudstack.storage.image.manager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -41,6 +43,7 @@ import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager; import org.apache.cloudstack.storage.image.datastore.ImageStoreProviderManager;
import org.apache.cloudstack.storage.image.store.ImageStoreImpl; import org.apache.cloudstack.storage.image.store.ImageStoreImpl;
import com.cloud.server.StatsCollector;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateDao;
@ -53,6 +56,8 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager
VMTemplateDao imageDataDao; VMTemplateDao imageDataDao;
@Inject @Inject
DataStoreProviderManager providerManager; DataStoreProviderManager providerManager;
@Inject
StatsCollector _statsCollector;
Map<String, ImageStoreDriver> driverMaps; Map<String, ImageStoreDriver> driverMaps;
@PostConstruct @PostConstruct
@ -137,4 +142,21 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager
} }
return imageStores; return imageStores;
} }
@Override
public DataStore getImageStore(List<DataStore> imageStores) {
if (imageStores.size() > 1) {
Collections.shuffle(imageStores); // Randomize image store list.
Iterator<DataStore> i = imageStores.iterator();
DataStore imageStore = null;
while(i.hasNext()) {
imageStore = i.next();
// Return image store if used percentage is less then threshold value i.e. 90%.
if (_statsCollector.imageStoreHasEnoughCapacity(imageStore)) {
return imageStore;
}
}
}
return imageStores.get(0);
}
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.apache.cloudstack.storage.datastore; package org.apache.cloudstack.storage.datastore;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
@ -79,8 +78,7 @@ public class DataStoreManagerImpl implements DataStoreManager {
if (stores == null || stores.size() == 0) { if (stores == null || stores.size() == 0) {
return null; return null;
} }
Collections.shuffle(stores); return imageDataStoreMgr.getImageStore(stores);
return stores.get(0);
} }
@Override @Override
@ -112,8 +110,7 @@ public class DataStoreManagerImpl implements DataStoreManager {
if (stores == null || stores.size() == 0) { if (stores == null || stores.size() == 0) {
return null; return null;
} }
Collections.shuffle(stores); return imageDataStoreMgr.getImageStore(stores);
return stores.get(0);
} }
@Override @Override

View File

@ -41,4 +41,6 @@ public interface ImageStoreProviderManager {
List<DataStore> listImageCacheStores(Scope scope); List<DataStore> listImageCacheStores(Scope scope);
boolean registerDriver(String uuid, ImageStoreDriver driver); boolean registerDriver(String uuid, ImageStoreDriver driver);
DataStore getImageStore(List<DataStore> imageStores);
} }

View File

@ -212,6 +212,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
long autoScaleStatsInterval = -1L; long autoScaleStatsInterval = -1L;
int vmDiskStatsInterval = 0; int vmDiskStatsInterval = 0;
List<Long> hostIds = null; List<Long> hostIds = null;
private double _imageStoreCapacityThreshold = 0.90;
String externalStatsPrefix = ""; String externalStatsPrefix = "";
String externalStatsHost = null; String externalStatsHost = null;
@ -1045,6 +1046,14 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc
} }
} }
public boolean imageStoreHasEnoughCapacity(DataStore imageStore) {
StorageStats imageStoreStats = _storageStats.get(imageStore.getId());
if (imageStoreStats != null && (imageStoreStats.getByteUsed()/(imageStoreStats.getCapacityBytes()*1.0)) <= _imageStoreCapacityThreshold) {
return true;
}
return false;
}
public StorageStats getStorageStats(long id) { public StorageStats getStorageStats(long id) {
return _storageStats.get(id); return _storageStats.get(id);
} }

View File

@ -60,6 +60,7 @@ import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceAllocationException;
import com.cloud.org.Grouping; import com.cloud.org.Grouping;
import com.cloud.server.StatsCollector;
import com.cloud.storage.ScopeType; import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.ImageFormat;
import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.Storage.TemplateType;
@ -83,8 +84,10 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
DownloadMonitor _downloadMonitor; DownloadMonitor _downloadMonitor;
@Inject @Inject
AgentManager _agentMgr; AgentManager _agentMgr;
@Inject
@Inject TemplateDataStoreDao templateDataStoreDao; StatsCollector _statsCollector;
@Inject
TemplateDataStoreDao templateDataStoreDao;
@Inject @Inject
DataStoreManager storeMgr; DataStoreManager storeMgr;
@Inject @Inject
@ -164,13 +167,17 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase {
continue; continue;
} }
// Check if image store has enough capacity for template
if (!_statsCollector.imageStoreHasEnoughCapacity(imageStore)) {
s_logger.info("Image store doesn't has enough capacity, so skip downloading template to this image store " + imageStore.getId());
continue;
}
// We want to download private template to one of the image store in a zone // We want to download private template to one of the image store in a zone
if(isPrivateTemplate(template) && zoneSet.contains(zoneId)){ if(isPrivateTemplate(template) && zoneSet.contains(zoneId)){
continue; continue;
}else { }else {
zoneSet.add(zoneId); zoneSet.add(zoneId);
} }
} }
TemplateInfo tmpl = imageFactory.getTemplate(template.getId(), imageStore); TemplateInfo tmpl = imageFactory.getTemplate(template.getId(), imageStore);