use of com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation in project coprhd-controller by CoprHD.
the class SRDFScheduler method populateSRDFPoolList.
/**
* Create an entry in the SRDF pool list if the source and destination storage systems can see
* each other via SRDF links.
*
* @param sourceVarray
* source varray
* @param destPoolStorageMap
* convenience, storage systems that belong to pools
* @param srcDestPoolList
* source/dest pool lists from earlier pool mapping
* @param sourcePool
* source pool being tested
* @param targetVarray
* target varray
* @param vpool
* source vpool
* @param vpoolChangeVolume
* source volume (null if not exists)
* @param size
* required volume size
*/
private void populateSRDFPoolList(final VirtualArray sourceVarray, final Map<StoragePool, StorageSystem> destPoolStorageMap, final Set<SRDFPoolMapping> srcDestPoolList, final StoragePool sourcePool, final VirtualArray targetVarray, final VirtualPool vpool, final Volume vpoolChangeVolume, final long size) {
StorageSystem storageSystem = _dbClient.queryObject(StorageSystem.class, sourcePool.getStorageDevice());
boolean isThinlyProvisioned = vpool.getSupportedProvisioningType().equalsIgnoreCase(VirtualPool.ProvisioningType.Thin.toString());
MetaVolumeRecommendation sourceVolumeRecommendation = MetaVolumeUtils.getCreateRecommendation(storageSystem, sourcePool, size, isThinlyProvisioned, vpool.getFastExpansion(), null);
long sourceMaxVolumeSizeLimitKb = isThinlyProvisioned ? sourcePool.getMaximumThinVolumeSize() : sourcePool.getMaximumThickVolumeSize();
_log.debug(String.format("Check which target pools match source pool %s based on the required volume configuration", sourcePool.getNativeId()));
for (StoragePool targetPool : destPoolStorageMap.keySet()) {
// supports the vpool policy (async/sync)
if (!storageSystem.containsRemotelyConnectedTo(targetPool.getStorageDevice())) {
continue;
}
// Check that target pool can support required volume configuration.
if (!validateRequiredVolumeConfiguration(sourcePool, targetPool, vpoolChangeVolume, destPoolStorageMap, sourceVolumeRecommendation, size, isThinlyProvisioned, vpool.getFastExpansion(), sourceMaxVolumeSizeLimitKb)) {
continue;
}
SRDFPoolMapping srdfPoolMapping = new SRDFPoolMapping();
srdfPoolMapping.sourceStoragePool = sourcePool;
srdfPoolMapping.sourceVarray = sourceVarray;
srdfPoolMapping.destStoragePool = targetPool;
srdfPoolMapping.destVarray = targetVarray;
srcDestPoolList.add(srdfPoolMapping);
}
}
use of com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation in project coprhd-controller by CoprHD.
the class MetaVolumeUtils method createAsMetaVolume.
/**
* Helper method to return if a given storage volume should be created as meta volume.
*
* @param volumeURI
* @param dbClient
* @return true/false
*/
public static boolean createAsMetaVolume(URI volumeURI, DbClient dbClient, VirtualPoolCapabilityValuesWrapper capabilities) {
boolean createAsMetaVolume = false;
// Check if volumes have to be created as meta volumes
Volume volume = dbClient.queryObject(Volume.class, volumeURI);
VirtualPool vPool = dbClient.queryObject(VirtualPool.class, volume.getVirtualPool());
StorageSystem storageSystem = dbClient.queryObject(StorageSystem.class, volume.getStorageController());
StoragePool storagePool = dbClient.queryObject(StoragePool.class, volume.getPool());
MetaVolumeRecommendation recommendation = MetaVolumeUtils.getCreateRecommendation(storageSystem, storagePool, volume.getCapacity(), volume.getThinlyProvisioned(), vPool.getFastExpansion(), capabilities);
if (recommendation.isCreateMetaVolumes()) {
createAsMetaVolume = true;
}
return createAsMetaVolume;
}
use of com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation in project coprhd-controller by CoprHD.
the class MetaVolumeUtils method getExpandRecommendation.
/**
* Returns recommendation about volume extension.
* The recommendation includes if meta volumes should be used, meta member count, meta member capacity and meta volume type.
*
* @param storageSystem storage system
* @param storagePool storage pool in which volume should be created
* @param capacity current size
* @param newCapacity new required size
* @param metaMemberSize size of meta members used for expansion
* @param fastExpansion if fast volume expansion is required
* @return recommendation
*/
public static MetaVolumeRecommendation getExpandRecommendation(StorageSystem storageSystem, StoragePool storagePool, long capacity, long newCapacity, long metaMemberSize, boolean isThinlyProvisioned, boolean fastExpansion) {
_log.info(String.format("Create recommendation for volume expansion: Storage type: %s, \n capacity: %s, new capacity: %s, \n isThinlyProvisioned: %s, " + "metaMemeberSize: %s, fastExpansion: %s ", storageSystem.getSystemType(), capacity, newCapacity, isThinlyProvisioned, metaMemberSize, fastExpansion));
MetaVolumeRecommendation recommendation = new MetaVolumeRecommendation();
if (getDriverManager() != null && getDriverManager().isDriverManaged(storageSystem.getSystemType())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Expand Recommendation (system type: %s): Use meta volumes: %s", storageSystem.getSystemType(), recommendation.isCreateMetaVolumes()));
return recommendation;
}
if (storageSystem.checkIfVmax3()) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Expand Recommendation (VMAX3): Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
if (storageSystem.getSystemType().equals(StorageSystem.Type.xtremio.name())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// For Clarion Unified pool and VNXe pool extension can be done only as regular volume
if (null != storagePool.getPoolClassName() && (storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.Clar_UnifiedStoragePool.toString()) || storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.VNXe_Pool.toString()))) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// For Hitachi thin volume expansion can be done as regular volume
if (isThinlyProvisioned && storageSystem.getSystemType().equals(StorageSystem.Type.hds.name())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Hitachi Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// For Openstack, volume expansion can be done as regular volume
if (StorageSystem.Type.openstack.name().equalsIgnoreCase(storageSystem.getSystemType())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Openstack Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
if (storageSystem.getSystemType().equals(StorageSystem.Type.scaleio.name())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("ScaleIO Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// For IBM XIV, volume expansion can be done as regular volume
if (StorageSystem.Type.ibmxiv.name().equalsIgnoreCase(storageSystem.getSystemType())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("IBM XIV Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
if (storageSystem.getSystemType().equals(StorageSystem.Type.ceph.name())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Ceph Volume Expand Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// For all other volume types we have to use meta volumes for extension
recommendation.setCreateMetaVolumes(true);
// Use concatenated volumes for fast expansion on VMAX. When fast expansion is not requested, use striped type on VMAX.
if (fastExpansion && storageSystem.getSystemType().equals(StorageSystem.Type.vmax.toString())) {
recommendation.setMetaVolumeType(Volume.CompositionType.CONCATENATED);
} else {
recommendation.setMetaVolumeType(Volume.CompositionType.STRIPED);
}
// All types of VNX volumes can be expanded fast (is this true?).
if (storageSystem.getSystemType().equals(StorageSystem.Type.vnxblock.toString())) {
Volume.CompositionType metaType = isThinlyProvisioned ? Volume.CompositionType.CONCATENATED : Volume.CompositionType.STRIPED;
recommendation.setMetaVolumeType(metaType);
}
// As per the Hitachi documentation, if a volume is exported then the data is safe when we expand, else data will be lost.
if (StorageSystem.Type.hds.name().equals(storageSystem.getSystemType()) && !isThinlyProvisioned) {
recommendation.setMetaVolumeType(Volume.CompositionType.CONCATENATED);
}
// Check if capacity bigger than newCapacity. In this case no expansion is required.
if (capacity >= newCapacity) {
recommendation.setMetaMemberSize(0);
recommendation.setMetaMemberCount(0);
} else {
// Calculate number of meta members for extension
long extensionSize = newCapacity - capacity;
long metaMemberCount = (extensionSize % metaMemberSize == 0) ? extensionSize / metaMemberSize : extensionSize / metaMemberSize + 1;
recommendation.setMetaMemberSize(metaMemberSize);
recommendation.setMetaMemberCount(metaMemberCount);
}
_log.info(String.format("Volume Expand Recommendation: Use meta volumes: %s, Member Count: %s, Member size: %s, Meta type: %s", recommendation.isCreateMetaVolumes(), recommendation.getMetaMemberCount(), recommendation.getMetaMemberSize(), recommendation.getMetaVolumeType()));
return recommendation;
}
use of com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation in project coprhd-controller by CoprHD.
the class MetaVolumeUtils method getCreateRecommendation.
/**
* Returns recommendation about use of meta volumes.
* The recommendation includes if meta volumes should be used, meta member count, meta member capacity and meta volume type.
*
* @param storageSystem storage system
* @param storagePool storage pool in which volume should be created
* @param capacity required size of volume
* @param isThinlyProvisioned
* @param fastExpansion if fast volume expansion is required
* @return recommendation
*/
public static MetaVolumeRecommendation getCreateRecommendation(StorageSystem storageSystem, StoragePool storagePool, long capacity, boolean isThinlyProvisioned, boolean fastExpansion, VirtualPoolCapabilityValuesWrapper capabilities) {
_log.info(String.format("Create recommendation for use of meta volumes: Storage type: %s, \n capacity: %s, isThinlyProvisioned: %s, " + "fastExpansion: %s ", storageSystem.getSystemType(), capacity, isThinlyProvisioned, fastExpansion));
MetaVolumeRecommendation recommendation = new MetaVolumeRecommendation();
// For driver managed system we use regular volumes.
if (getDriverManager() != null && getDriverManager().isDriverManaged(storageSystem.getSystemType())) {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Create Recommendation (system type: %s): Use meta volumes: %s", storageSystem.getSystemType(), recommendation.isCreateMetaVolumes()));
return recommendation;
}
// This is used to create srdf target with meta structure identical to the srdf source volume.
if (capabilities != null && capabilities.getIsMetaVolume()) {
recommendation.setCreateMetaVolumes(true);
if (capabilities.getMetaVolumeType().equalsIgnoreCase(Volume.CompositionType.CONCATENATED.toString())) {
recommendation.setMetaVolumeType(Volume.CompositionType.CONCATENATED);
} else if (capabilities.getMetaVolumeType().equalsIgnoreCase(Volume.CompositionType.STRIPED.toString())) {
recommendation.setMetaVolumeType(Volume.CompositionType.STRIPED);
}
recommendation.setMetaMemberSize(capabilities.getMetaVolumeMemberSize());
recommendation.setMetaMemberCount(capabilities.getMetaVolumeMemberCount());
_log.info(String.format("Volume Create Recommendation (based on capabilities data): Use meta volumes: %s, Member Count: %s, Member size: %s, Meta type: %s", recommendation.isCreateMetaVolumes(), recommendation.getMetaMemberCount(), recommendation.getMetaMemberSize(), recommendation.getMetaVolumeType()));
return recommendation;
}
if (null == storagePool.getPoolClassName() || storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.Symm_SRPStoragePool.toString()) || storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.IBMTSDS_VirtualPool.toString()) || storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.Clar_UnifiedStoragePool.toString()) || storagePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.VNXe_Pool.name())) {
// If the pool class name is not set, then it's not necessary to do MetaVolumes
// meta volumes are not supported for clarion volumes created in Unified pools, and not supported in VNXe either.
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Create Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
return recommendation;
}
// On VMAX arrays only concatenated meta volumes can be expanded fast.
// If fast expansion is required use concatenated, otherwise use striped.
// On VNX we always use striped. No penalty for striped expansion on VNX (is this true?).
Volume.CompositionType metaVolumeType;
if (fastExpansion && storageSystem.getSystemType().equals(StorageSystem.Type.vmax.toString())) {
metaVolumeType = Volume.CompositionType.CONCATENATED;
} else {
metaVolumeType = Volume.CompositionType.STRIPED;
}
_log.info(String.format("Regular volume capacity limits for storage pool %s, %n max thin volume capacity: %s, max thick volume capacity: %s ", storagePool.getId(), storagePool.getMaximumThinVolumeSize(), storagePool.getMaximumThickVolumeSize()));
// Get storage pool setting for maximum supported regular volume size.
// Typically this size is 240GB, but it can be different on VMAX if auto meta configuration is enabled and minimum meta volume size
// is defined there
// less than 240GB.
long regularVolumeSizeLimitKb = isThinlyProvisioned ? storagePool.getMaximumThinVolumeSize() : storagePool.getMaximumThickVolumeSize();
_log.info(String.format("Regular volume size limit for storage pool: %s KB", regularVolumeSizeLimitKb));
long capacityKb = (capacity % BYTESCONVERTER == 0) ? capacity / BYTESCONVERTER : capacity / BYTESCONVERTER + 1;
// TODO temporary. remove later
// regularVolumeSizeLimitKb = 1048576 + 10; // 1GB + 10 kb
// Check if we need to use meta volumes.
// Use meta volumes when capacity is large than maximum regular volume size limit.
// This is a common case.
boolean useMetaVolumes = false;
long metaMemberCount = 1;
if (capacityKb >= regularVolumeSizeLimitKb) {
useMetaVolumes = true;
// Calculate meta member count
metaMemberCount = (capacityKb % regularVolumeSizeLimitKb == 0) ? capacityKb / regularVolumeSizeLimitKb : capacityKb / regularVolumeSizeLimitKb + 1;
}
// I do not see any issues with this and I added this support.
if (storageSystem.getSystemType().equals(StorageSystem.Type.vmax.toString()) && metaVolumeType == Volume.CompositionType.STRIPED) {
long maxLimitWith16Members = 16 * regularVolumeSizeLimitKb;
long maxLimitWith32Members = 32 * regularVolumeSizeLimitKb;
if (isThinlyProvisioned) {
// create 8-way meta up to max possible size
if (capacityKb >= regularVolumeSizeLimitKb && capacityKb < 8 * regularVolumeSizeLimitKb) {
metaMemberCount = 8;
useMetaVolumes = true;
} else if (capacityKb >= 8 * regularVolumeSizeLimitKb && capacityKb < maxLimitWith16Members) {
metaMemberCount = 16;
useMetaVolumes = true;
} else if (capacityKb >= maxLimitWith16Members && capacityKb < maxLimitWith32Members) {
metaMemberCount = 32;
useMetaVolumes = true;
}
} else {
// thick striped meta, use the following rules
// Current rules are to use 4 way meta for volumes between 32GB and 500GB, 8 way meta for volumes between 500GB and 1024GB,
// 16 way meta for volumes from 1024 and up. After that increase meta members count as needed according to max. regular
// volume size limit.
// On VMAX with auto meta configuration enabled, regular volume size limit can be small and we need to account this to make
// sure we do not create
// members bigger than auto meta limit.
// SAP asked to continue with 32 members after we exhausted 16 member capacity. I do not see any issues with
// this and I added this support.
long minimumMetaSizeLimit = (GB_32kb < regularVolumeSizeLimitKb) ? GB_32kb : regularVolumeSizeLimitKb;
long maxLimitWith4Members = (GB_500kb < 4 * regularVolumeSizeLimitKb) ? GB_500kb : 4 * regularVolumeSizeLimitKb;
long maxLimitWith8Members = (GB_1024kb < 8 * regularVolumeSizeLimitKb) ? GB_1024kb : 8 * regularVolumeSizeLimitKb;
if (capacityKb >= minimumMetaSizeLimit && capacityKb < maxLimitWith4Members) {
metaMemberCount = 4;
useMetaVolumes = true;
} else if (capacityKb >= maxLimitWith4Members && capacityKb < maxLimitWith8Members) {
metaMemberCount = 8;
useMetaVolumes = true;
} else if (capacityKb >= maxLimitWith8Members && capacityKb < maxLimitWith16Members) {
metaMemberCount = 16;
useMetaVolumes = true;
} else if (capacityKb >= maxLimitWith16Members && capacityKb < maxLimitWith32Members) {
metaMemberCount = 32;
useMetaVolumes = true;
}
}
}
if (useMetaVolumes) {
long metaMemberSize = (capacity % metaMemberCount == 0) ? capacity / metaMemberCount : capacity / metaMemberCount + 1;
recommendation.setCreateMetaVolumes(true);
recommendation.setMetaVolumeType(metaVolumeType);
recommendation.setMetaMemberSize(metaMemberSize);
recommendation.setMetaMemberCount(metaMemberCount);
_log.info(String.format("Volume Create Recommendation: Use meta volumes: %s, Member Count: %s, Member size: %s, Meta type: %s", recommendation.isCreateMetaVolumes(), recommendation.getMetaMemberCount(), recommendation.getMetaMemberSize(), recommendation.getMetaVolumeType()));
} else {
recommendation.setCreateMetaVolumes(false);
_log.info(String.format("Volume Create Recommendation: Use meta volumes: %s", recommendation.isCreateMetaVolumes()));
}
return recommendation;
}
use of com.emc.storageos.volumecontroller.impl.smis.MetaVolumeRecommendation in project coprhd-controller by CoprHD.
the class SRDFScheduler method validateRequiredVolumeConfiguration.
/**
* Check if target pool can support required volume configuration for srdf target volume.
*
* @param sourcePool
* @param targetPool
* @param vpoolChangeVolume source volume (null if not exists)
* @param destPoolStorageMap map target pool to storage system
* @param sourceVolumeRecommendation
* @param size required volume size
* @param isThinlyProvisioned
* @param fastExpansion
* @param sourceMaxVolumeSizeLimitKb
* @return true/false
*/
private boolean validateRequiredVolumeConfiguration(StoragePool sourcePool, StoragePool targetPool, Volume vpoolChangeVolume, Map<StoragePool, StorageSystem> destPoolStorageMap, MetaVolumeRecommendation sourceVolumeRecommendation, long size, boolean isThinlyProvisioned, boolean fastExpansion, long sourceMaxVolumeSizeLimitKb) {
long targetMaxVolumeSizeLimitKb = isThinlyProvisioned ? targetPool.getMaximumThinVolumeSize() : targetPool.getMaximumThickVolumeSize();
if (sourceMaxVolumeSizeLimitKb == targetMaxVolumeSizeLimitKb) {
// pool will support required volume configuration.
return true;
}
_log.info(String.format("Target storage pool %s max volume size limit %s Kb. Source storage pool max volume size limit %s Kb.", targetPool.getNativeId(), targetMaxVolumeSizeLimitKb, sourceMaxVolumeSizeLimitKb));
// Keeping the below information as it will be handy
StorageSystem targetStorageSystem = destPoolStorageMap.get(targetPool);
MetaVolumeRecommendation targetVolumeRecommendation = MetaVolumeUtils.getCreateRecommendation(targetStorageSystem, targetPool, size, isThinlyProvisioned, fastExpansion, null);
if (vpoolChangeVolume != null) {
// This is path to upgrade existing volume to srdf protected volume
if (vpoolChangeVolume.getIsComposite()) {
// Existing volume is composite volume.
// Make sure that the target pool will allow to create META MEMBERS of required size if it is a VMAX2 Array.
// If it is a VMAX3 Array, make sure that the target Pool will allow creation of the a SINGLE VOLUME
long capacity = vpoolChangeVolume.getMetaMemberSize();
long capacityKb = (capacity % BYTESCONVERTER == 0) ? capacity / BYTESCONVERTER : capacity / BYTESCONVERTER + 1;
if (targetStorageSystem.checkIfVmax3()) {
// recompute the capacity for checks
capacityKb = capacityKb * vpoolChangeVolume.getMetaMemberCount();
}
if (capacityKb > targetMaxVolumeSizeLimitKb) {
// this target pool does not match --- does not support meta members of the required size
_log.debug(String.format("Target storage pool %s does not match. Limit for volume size is less than required by source volume configuration \n" + "Required capacity: %s Kb, actual limit: %s Kb", targetPool.getNativeId(), capacityKb, targetMaxVolumeSizeLimitKb));
return false;
}
} else {
// Existing volume is a regular volume.
// Check that the target pool will allow to create regular volume of the same size or META MEMBERS if
// the target volume is going to be a META
long capacity = vpoolChangeVolume.getCapacity();
if (targetVolumeRecommendation.isCreateMetaVolumes() && (sourcePool.getPoolClassName().equalsIgnoreCase(StoragePool.PoolClassNames.Symm_SRPStoragePool.toString()))) {
// recompute the capacity for checks
capacity = targetVolumeRecommendation.getMetaMemberSize();
}
long capacityKb = (capacity % BYTESCONVERTER == 0) ? capacity / BYTESCONVERTER : capacity / BYTESCONVERTER + 1;
if (capacityKb > targetMaxVolumeSizeLimitKb) {
// this target pool does not match --- does not support regular volumes of the required size
_log.debug(String.format("Target storage pool %s does not match. Limit for volume size is less than required by source volume configuration \n" + "Required capacity: %s Kb, actual limit: %s Kb", targetPool.getNativeId(), capacityKb, targetMaxVolumeSizeLimitKb));
return false;
}
}
} else {
// Verify meta volume recommendation for target pool and check if we get the same volume spec as for the source volume.
return validateMetaRecommednationsForSRDF(sourcePool, targetPool, sourceVolumeRecommendation, targetVolumeRecommendation);
}
return true;
}
Aggregations