Fix slow vm creation when large sf snapshot count (#3282)

* skip geting used bytes for volumes that are not in Ready state
* updated log message
* filter snapshots by state backedup
* removed * import
* filter templates by state 'DOWNLOADED'
* refactored getUsedBytes to use O(1) queries
* querying for ready volumes instead filtering in memory
* make listByStoreIdInReadyState more generic ex listByStoreIdAndState
* updated snapshot search criteria for listByStoreIdAndState
* updated template search criteria for listByPoolIdAndState
* fixed typo in search criteria for listByTemplateAndState
* fixed typo in search criteria for templates in listByPoolIdAndState
This commit is contained in:
skattoju4 2019-05-11 10:02:52 -04:00 committed by Sven Vogel
parent 67160478a6
commit 4c60a5b1ff
7 changed files with 66 additions and 54 deletions

View File

@ -33,6 +33,8 @@ public interface VMTemplatePoolDao extends GenericDao<VMTemplateStoragePoolVO, L
public VMTemplateStoragePoolVO findByPoolTemplate(long poolId, long templateId);
public List<VMTemplateStoragePoolVO> listByPoolIdAndState(long poolId, ObjectInDataStoreStateMachine.State state);
public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState);
public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId);

View File

@ -24,11 +24,13 @@ import java.util.List;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
@ -55,6 +57,7 @@ public class VMTemplatePoolDaoImpl extends GenericDaoBase<VMTemplateStoragePoolV
protected final SearchBuilder<VMTemplateStoragePoolVO> TemplateStatusSearch;
protected final SearchBuilder<VMTemplateStoragePoolVO> TemplatePoolStatusSearch;
protected final SearchBuilder<VMTemplateStoragePoolVO> TemplateStatesSearch;
protected final SearchBuilder<VMTemplateStoragePoolVO> TemplatePoolStateSearch;
protected final SearchBuilder<VMTemplateStoragePoolVO> updateStateSearch;
protected static final String UPDATE_TEMPLATE_HOST_REF = "UPDATE template_spool_ref SET download_state = ?, download_pct= ?, last_updated = ? "
@ -96,6 +99,11 @@ public class VMTemplatePoolDaoImpl extends GenericDaoBase<VMTemplateStoragePoolV
TemplatePoolStatusSearch.and("download_state", TemplatePoolStatusSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
TemplatePoolStatusSearch.done();
TemplatePoolStateSearch = createSearchBuilder();
TemplatePoolStateSearch.and("pool_id", TemplatePoolStateSearch.entity().getPoolId(), SearchCriteria.Op.EQ);
TemplatePoolStateSearch.and("state", TemplatePoolStateSearch.entity().getState(), SearchCriteria.Op.EQ);
TemplatePoolStateSearch.done();
TemplateStatesSearch = createSearchBuilder();
TemplateStatesSearch.and("template_id", TemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
TemplateStatesSearch.and("states", TemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.IN);
@ -138,6 +146,14 @@ public class VMTemplatePoolDaoImpl extends GenericDaoBase<VMTemplateStoragePoolV
return listIncludingRemovedBy(sc);
}
@Override
public List<VMTemplateStoragePoolVO> listByPoolIdAndState(long poolId, ObjectInDataStoreStateMachine.State state) {
SearchCriteria<VMTemplateStoragePoolVO> sc = TemplatePoolStateSearch.create();
sc.setParameters("pool_id", poolId);
sc.setParameters("state", state);
return listIncludingRemovedBy(sc);
}
@Override
public List<VMTemplateStoragePoolVO> listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId) {
SearchCriteria<VMTemplateStoragePoolVO> sc = TemplatePoolStatusSearch.create();

View File

@ -72,6 +72,8 @@ public interface VolumeDao extends GenericDao<VolumeVO, Long>, StateDao<Volume.S
List<VolumeVO> findByPoolId(long poolId, Volume.Type volumeType);
List<VolumeVO> findByPoolIdAndState(long poolid, Volume.State state);
List<VolumeVO> findByInstanceAndDeviceId(long instanceId, long deviceId);
List<VolumeVO> findUsableVolumesForInstance(long instanceId);

View File

@ -148,6 +148,14 @@ public class VolumeDaoImpl extends GenericDaoBase<VolumeVO, Long> implements Vol
return listBy(sc);
}
@Override
public List<VolumeVO> findByPoolIdAndState(long poolId, Volume.State state) {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();
sc.setParameters("poolId", poolId);
sc.setParameters("state", state);
return listBy(sc);
}
@Override
public List<VolumeVO> findCreatedByInstance(long id) {
SearchCriteria<VolumeVO> sc = AllFieldsSearch.create();

View File

@ -30,6 +30,8 @@ StateDao<ObjectInDataStoreStateMachine.State, ObjectInDataStoreStateMachine.Even
List<SnapshotDataStoreVO> listByStoreId(long id, DataStoreRole role);
List<SnapshotDataStoreVO> listByStoreIdAndState(long id, ObjectInDataStoreStateMachine.State state);
List<SnapshotDataStoreVO> listActiveOnCache(long id);
void deletePrimaryRecordsForStore(long id, DataStoreRole role);

View File

@ -27,6 +27,8 @@ import java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.SnapshotVO;
import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
@ -37,8 +39,6 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.SnapshotVO;
import com.cloud.storage.dao.SnapshotDao;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
@ -54,6 +54,7 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
private static final Logger s_logger = Logger.getLogger(SnapshotDataStoreDaoImpl.class);
private SearchBuilder<SnapshotDataStoreVO> updateStateSearch;
private SearchBuilder<SnapshotDataStoreVO> storeSearch;
private SearchBuilder<SnapshotDataStoreVO> storeStateSearch;
private SearchBuilder<SnapshotDataStoreVO> destroyedSearch;
private SearchBuilder<SnapshotDataStoreVO> cacheSearch;
private SearchBuilder<SnapshotDataStoreVO> snapshotSearch;
@ -92,6 +93,11 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
storeSearch.and("state", storeSearch.entity().getState(), SearchCriteria.Op.NEQ);
storeSearch.done();
storeStateSearch = createSearchBuilder();
storeStateSearch.and("store_id", storeStateSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
storeStateSearch.and("state", storeStateSearch.entity().getState(), SearchCriteria.Op.EQ);
storeStateSearch.done();
destroyedSearch = createSearchBuilder();
destroyedSearch.and("store_id", destroyedSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ);
destroyedSearch.and("store_role", destroyedSearch.entity().getRole(), SearchCriteria.Op.EQ);
@ -221,6 +227,14 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase<SnapshotDataStoreVO
return listBy(sc);
}
@Override
public List<SnapshotDataStoreVO> listByStoreIdAndState(long id, ObjectInDataStoreStateMachine.State state) {
SearchCriteria<SnapshotDataStoreVO> sc = storeStateSearch.create();
sc.setParameters("store_id", id);
sc.setParameters("state", state);
return listBy(sc);
}
@Override
public void deletePrimaryRecordsForStore(long id, DataStoreRole role) {
SearchCriteria<SnapshotDataStoreVO> sc = storeSearch.create();

View File

@ -72,10 +72,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
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.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
import org.apache.cloudstack.storage.command.CommandResult;
import org.apache.cloudstack.storage.command.CreateObjectAnswer;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
@ -104,9 +107,10 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
@Inject private HostDao hostDao;
@Inject private SnapshotDao snapshotDao;
@Inject private SnapshotDetailsDao snapshotDetailsDao;
@Inject private SnapshotDataStoreDao snapshotDataStoreDao;
@Inject private PrimaryDataStoreDao storagePoolDao;
@Inject private StoragePoolDetailsDao storagePoolDetailsDao;
@Inject private VMTemplatePoolDao tmpltPoolDao;
@Inject private VMTemplatePoolDao vmTemplatePoolDao;
@Inject private VolumeDao volumeDao;
@Inject private VolumeDetailsDao volumeDetailsDao;
@Inject private VolumeDataFactory volumeFactory;
@ -360,7 +364,7 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
private long getUsedBytes(StoragePool storagePool, long volumeIdToIgnore) {
long usedSpace = 0;
List<VolumeVO> lstVolumes = volumeDao.findByPoolId(storagePool.getId(), null);
List<VolumeVO> lstVolumes = volumeDao.findByPoolIdAndState(storagePool.getId(), Volume.State.Ready);
if (lstVolumes != null) {
for (VolumeVO volume : lstVolumes) {
@ -368,62 +372,26 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
continue;
}
VolumeDetailVO volumeDetail = volumeDetailsDao.findDetail(volume.getId(), SolidFireUtil.VOLUME_SIZE);
usedSpace += getVolumeSizeIncludingHypervisorSnapshotReserve(volume.getSize(),volume.getHypervisorSnapshotReserve());
if (volumeDetail != null && volumeDetail.getValue() != null) {
long volumeSize = Long.parseLong(volumeDetail.getValue());
usedSpace += volumeSize;
}
else {
SolidFireUtil.SolidFireConnection sfConnection = SolidFireUtil.getSolidFireConnection(storagePool.getId(), storagePoolDetailsDao);
try {
long lVolumeId = Long.parseLong(volume.getFolder());
SolidFireUtil.SolidFireVolume sfVolume = SolidFireUtil.getVolume(sfConnection, lVolumeId);
long volumeSize = sfVolume.getTotalSize();
// SolidFireUtil.VOLUME_SIZE was introduced in 4.5.
// To be backward compatible with releases prior to 4.5, call updateVolumeDetails here.
// That way if SolidFireUtil.VOLUME_SIZE wasn't put in the volume_details table when the
// volume was initially created, it can be placed in volume_details here.
updateVolumeDetails(volume.getId(), volumeSize, sfVolume.getScsiNaaDeviceId());
usedSpace += volumeSize;
}
catch (Exception ex) {
// can be ignored
}
}
}
}
List<SnapshotVO> lstSnapshots = snapshotDao.listAll();
List<SnapshotDataStoreVO> snapshotDataStoreVOList = snapshotDataStoreDao.listByStoreIdAndState(storagePool.getId(), ObjectInDataStoreStateMachine.State.Ready);
if (lstSnapshots != null) {
for (SnapshotVO snapshot : lstSnapshots) {
SnapshotDetailsVO snapshotDetails = snapshotDetailsDao.findDetail(snapshot.getId(), SolidFireUtil.STORAGE_POOL_ID);
if (snapshotDataStoreVOList != null) {
for (SnapshotDataStoreVO snapshot : snapshotDataStoreVOList) {
// if this snapshot belongs to the storagePool that was passed in
if (snapshotDetails != null && snapshotDetails.getValue() != null && Long.parseLong(snapshotDetails.getValue()) == storagePool.getId()) {
snapshotDetails = snapshotDetailsDao.findDetail(snapshot.getId(), SolidFireUtil.VOLUME_SIZE);
usedSpace += snapshot.getPhysicalSize();
if (snapshotDetails != null && snapshotDetails.getValue() != null) {
long snapshotSize = Long.parseLong(snapshotDetails.getValue());
usedSpace += snapshotSize;
}
}
}
}
List<VMTemplateStoragePoolVO> lstTemplatePoolRefs = tmpltPoolDao.listByPoolId(storagePool.getId());
List<VMTemplateStoragePoolVO> vmTemplateStoragePoolVOList = vmTemplatePoolDao.listByPoolIdAndState(storagePool.getId(), ObjectInDataStoreStateMachine.State.Ready);
if (lstTemplatePoolRefs != null) {
for (VMTemplateStoragePoolVO templatePoolRef : lstTemplatePoolRefs) {
usedSpace += templatePoolRef.getTemplateSize();
if (vmTemplateStoragePoolVOList != null) {
for (VMTemplateStoragePoolVO template : vmTemplateStoragePoolVOList) {
usedSpace += template.getTemplateSize();
}
}
@ -487,7 +455,7 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
*/
@Override
public long getBytesRequiredForTemplate(TemplateInfo templateInfo, StoragePool storagePool) {
List<VMTemplateStoragePoolVO> lstTemplatePoolRefs = tmpltPoolDao.listByPoolId(storagePool.getId());
List<VMTemplateStoragePoolVO> lstTemplatePoolRefs = vmTemplatePoolDao.listByPoolId(storagePool.getId());
if (lstTemplatePoolRefs != null) {
for (VMTemplateStoragePoolVO templatePoolRef : lstTemplatePoolRefs) {
@ -740,7 +708,7 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
sfVolumeId = Long.parseLong(snapshotDetails.getValue());
} else if (dataObjectType == DataObjectType.TEMPLATE) {
// get the cached template on this storage
VMTemplateStoragePoolVO templatePoolRef = tmpltPoolDao.findByPoolTemplate(storagePoolId, dataObjectId);
VMTemplateStoragePoolVO templatePoolRef = vmTemplatePoolDao.findByPoolTemplate(storagePoolId, dataObjectId);
if (templatePoolRef != null) {
sfVolumeId = Long.parseLong(templatePoolRef.getLocalDownloadPath());
@ -1166,13 +1134,13 @@ public class SolidFirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
String iqn = sfVolume.getIqn();
VMTemplateStoragePoolVO templatePoolRef = tmpltPoolDao.findByPoolTemplate(storagePoolId, templateInfo.getId());
VMTemplateStoragePoolVO templatePoolRef = vmTemplatePoolDao.findByPoolTemplate(storagePoolId, templateInfo.getId());
templatePoolRef.setInstallPath(iqn);
templatePoolRef.setLocalDownloadPath(Long.toString(sfVolume.getId()));
templatePoolRef.setTemplateSize(sfVolume.getTotalSize());
tmpltPoolDao.update(templatePoolRef.getId(), templatePoolRef);
vmTemplatePoolDao.update(templatePoolRef.getId(), templatePoolRef);
StoragePoolVO storagePool = storagePoolDao.findById(storagePoolId);