From 4c60a5b1ff39b49171d59738c72cf217789b049a Mon Sep 17 00:00:00 2001 From: skattoju4 <45833770+skattoju4@users.noreply.github.com> Date: Sat, 11 May 2019 10:02:52 -0400 Subject: [PATCH] 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 --- .../cloud/storage/dao/VMTemplatePoolDao.java | 2 + .../storage/dao/VMTemplatePoolDaoImpl.java | 18 ++++- .../java/com/cloud/storage/dao/VolumeDao.java | 2 + .../com/cloud/storage/dao/VolumeDaoImpl.java | 8 +++ .../datastore/db/SnapshotDataStoreDao.java | 2 + .../image/db/SnapshotDataStoreDaoImpl.java | 18 ++++- .../SolidFirePrimaryDataStoreDriver.java | 70 +++++-------------- 7 files changed, 66 insertions(+), 54 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDao.java index 520416e34e7..6216ef77ca2 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDao.java @@ -33,6 +33,8 @@ public interface VMTemplatePoolDao extends GenericDao listByPoolIdAndState(long poolId, ObjectInDataStoreStateMachine.State state); + public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState); public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java index d2c4a99e6ae..bb3985f6dc7 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VMTemplatePoolDaoImpl.java @@ -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 TemplateStatusSearch; protected final SearchBuilder TemplatePoolStatusSearch; protected final SearchBuilder TemplateStatesSearch; + protected final SearchBuilder TemplatePoolStateSearch; protected final SearchBuilder 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 listByPoolIdAndState(long poolId, ObjectInDataStoreStateMachine.State state) { + SearchCriteria sc = TemplatePoolStateSearch.create(); + sc.setParameters("pool_id", poolId); + sc.setParameters("state", state); + return listIncludingRemovedBy(sc); + } + @Override public List listByTemplateStatus(long templateId, VMTemplateStoragePoolVO.Status downloadState, long poolId) { SearchCriteria sc = TemplatePoolStatusSearch.create(); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java index 51d46a06963..c0abb564de1 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java @@ -72,6 +72,8 @@ public interface VolumeDao extends GenericDao, StateDao findByPoolId(long poolId, Volume.Type volumeType); + List findByPoolIdAndState(long poolid, Volume.State state); + List findByInstanceAndDeviceId(long instanceId, long deviceId); List findUsableVolumesForInstance(long instanceId); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java index 663a5f5cfc8..fb25c54b2cf 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java @@ -148,6 +148,14 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol return listBy(sc); } + @Override + public List findByPoolIdAndState(long poolId, Volume.State state) { + SearchCriteria sc = AllFieldsSearch.create(); + sc.setParameters("poolId", poolId); + sc.setParameters("state", state); + return listBy(sc); + } + @Override public List findCreatedByInstance(long id) { SearchCriteria sc = AllFieldsSearch.create(); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java index 50f311a4eaa..819cb7bc6ce 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java @@ -30,6 +30,8 @@ StateDao listByStoreId(long id, DataStoreRole role); + List listByStoreIdAndState(long id, ObjectInDataStoreStateMachine.State state); + List listActiveOnCache(long id); void deletePrimaryRecordsForStore(long id, DataStoreRole role); diff --git a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java index 6ca6b239b6f..c7358d1558b 100644 --- a/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java +++ b/engine/storage/src/main/java/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java @@ -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 updateStateSearch; private SearchBuilder storeSearch; + private SearchBuilder storeStateSearch; private SearchBuilder destroyedSearch; private SearchBuilder cacheSearch; private SearchBuilder snapshotSearch; @@ -92,6 +93,11 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase listByStoreIdAndState(long id, ObjectInDataStoreStateMachine.State state) { + SearchCriteria sc = storeStateSearch.create(); + sc.setParameters("store_id", id); + sc.setParameters("state", state); + return listBy(sc); + } + @Override public void deletePrimaryRecordsForStore(long id, DataStoreRole role) { SearchCriteria sc = storeSearch.create(); diff --git a/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java index 370cdb0a7a3..19b678e4aeb 100644 --- a/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java +++ b/plugins/storage/volume/solidfire/src/main/java/org/apache/cloudstack/storage/datastore/driver/SolidFirePrimaryDataStoreDriver.java @@ -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 lstVolumes = volumeDao.findByPoolId(storagePool.getId(), null); + List 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 lstSnapshots = snapshotDao.listAll(); + List 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 lstTemplatePoolRefs = tmpltPoolDao.listByPoolId(storagePool.getId()); + List 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 lstTemplatePoolRefs = tmpltPoolDao.listByPoolId(storagePool.getId()); + List 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);