use of com.emc.storageos.volumecontroller.impl.utils.ProvisioningAttributeMapBuilder in project coprhd-controller by CoprHD.
the class CapacityUtils method getCapacityForVirtualPoolAndVirtualArray.
public static CapacityResponse getCapacityForVirtualPoolAndVirtualArray(VirtualPool vPool, URI vArrayId, DbClient dbClient, CoordinatorClient coordinator) {
List<StoragePool> validPoolsOfvPool = VirtualPool.getValidStoragePools(vPool, dbClient, false);
List<StoragePool> invalidPoolsOfvPool = VirtualPool.getInvalidStoragePools(vPool, dbClient);
Map<String, Object> attributeMap = new ProvisioningAttributeMapBuilder(0L, vArrayId.toString(), 0L).buildMap();
NeighborhoodsMatcher matcher = new NeighborhoodsMatcher();
matcher.setCoordinatorClient(coordinator);
matcher.setObjectCache(new ObjectLocalCache(dbClient));
StringBuffer errorMessageForValidPools = new StringBuffer();
StringBuffer errorMessageForInValidPools = new StringBuffer();
validPoolsOfvPool = matcher.runMatchStoragePools(validPoolsOfvPool, attributeMap, errorMessageForValidPools);
invalidPoolsOfvPool = matcher.runMatchStoragePools(invalidPoolsOfvPool, attributeMap, errorMessageForInValidPools);
List<StoragePool> validPools = new ArrayList<StoragePool>();
for (StoragePool pool : validPoolsOfvPool) {
if (StoragePool.RegistrationStatus.REGISTERED.toString().equals(pool.getRegistrationStatus()) && CompatibilityStatus.COMPATIBLE.toString().equals(pool.getCompatibilityStatus()) && DiscoveryStatus.VISIBLE.toString().equals(pool.getDiscoveryStatus())) {
validPools.add(pool);
} else {
invalidPoolsOfvPool.add(pool);
}
}
Map<String, BigInteger> rawCapacityMetrics = getPoolCapacityMetrics(validPools, vPool, dbClient, coordinator);
Set<String> poolSet = new HashSet<String>();
for (StoragePool pool : validPools) {
poolSet.add(pool.getId().toString());
}
Capacity capacity = getVirtualPoolCapacityForPools(dbClient, vPool.getId(), VirtualPool.Type.valueOf(vPool.getType()), poolSet);
poolSet.clear();
for (StoragePool pool : invalidPoolsOfvPool) {
poolSet.add(pool.getId().toString());
}
Capacity invalidPoolCapacity = getVirtualPoolCapacityForPools(dbClient, vPool.getId(), VirtualPool.Type.valueOf(vPool.getType()), poolSet);
// Free Capacity is rounded down
BigInteger freeCapacity = rawCapacityMetrics.get(StorageMetrics.FREE.toString());
freeCapacity = freeCapacity.divide(kbToGB_BI);
long freeCapacityGb = freeCapacity.longValue();
BigInteger netFreeCapacity = rawCapacityMetrics.get(StorageMetrics.NET_FREE.toString());
netFreeCapacity = netFreeCapacity.divide(kbToGB_BI);
long netFreeCapacityGb = netFreeCapacity.longValue();
// 4) Check netFreeCapacity against Quota
if (vPool.getQuotaEnabled()) {
long netFreeQuota = vPool.getQuota() - (long) ((capacity._provisionedCapacity + invalidPoolCapacity._provisionedCapacity) / GB);
if (netFreeQuota < 0) {
netFreeCapacityGb = 0;
} else if (netFreeQuota < netFreeCapacityGb) {
netFreeCapacityGb = netFreeQuota;
}
}
// Used Capacity is rounded up.
BigDecimal[] result = new BigDecimal(capacity._usedCapacity + invalidPoolCapacity._usedCapacity).divideAndRemainder(new BigDecimal(GB));
long usedCapacityGb = result[0].longValue();
if (!result[1].equals(BigDecimal.ZERO)) {
usedCapacityGb += 1;
}
// Subscribed Capacity is rounded up.
result = new BigDecimal(capacity._provisionedCapacity + invalidPoolCapacity._provisionedCapacity).divideAndRemainder(new BigDecimal(GB));
long subscribedCapacityGb = result[0].longValue();
if (!result[1].equals(BigDecimal.ZERO)) {
subscribedCapacityGb += 1;
}
long totalCapacityGB = freeCapacityGb + usedCapacityGb;
CapacityResponse response = new CapacityResponse();
response.setFreeGb(Long.toString(freeCapacityGb));
response.setNetFreeGb(Long.toString(netFreeCapacityGb));
response.setProvissionedGb(Long.toString(subscribedCapacityGb));
response.setUsedGb(Long.toString(usedCapacityGb));
if (totalCapacityGB != 0) {
result = new BigDecimal(subscribedCapacityGb * 100).divideAndRemainder(new BigDecimal(totalCapacityGB));
int percentage = result[0].intValue();
if (!result[1].equals(BigDecimal.ZERO)) {
percentage += 1;
}
response.setPercentProvisioned(Integer.toString(percentage));
result = new BigDecimal(usedCapacityGb * 100).divideAndRemainder(new BigDecimal(totalCapacityGB));
percentage = result[0].intValue();
if (!result[1].equals(BigDecimal.ZERO)) {
percentage += 1;
}
response.setPercentUsed(Integer.toString(percentage));
}
return response;
}
use of com.emc.storageos.volumecontroller.impl.utils.ProvisioningAttributeMapBuilder in project coprhd-controller by CoprHD.
the class StorageScheduler method getMatchingPools.
/**
* Select candidate storage pools for placement.
*
* @param varray The VirtualArray for matching storage pools.
* @param vpool The virtualPool that must be satisfied by the storage pool.
* @param capabilities The VirtualPool params that must be satisfied.
* @param optionalAttributes Optional addition attributes to consider for placement
*
* @return A list of matching storage pools.
*/
protected List<StoragePool> getMatchingPools(VirtualArray varray, VirtualPool vpool, VirtualPoolCapabilityValuesWrapper capabilities, Map<String, Object> optionalAttributes) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.VARRAYS, varray.getId().toString());
if (null != vpool.getAutoTierPolicyName()) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.AUTO_TIER__POLICY_NAME, vpool.getAutoTierPolicyName());
}
List<StoragePool> storagePools = new ArrayList<StoragePool>();
String varrayId = varray.getId().toString();
StringBuffer errorMessage = new StringBuffer();
// Verify that if the VirtualPool has been assigned one or more VirtualArrays,
// there is a match with the passed VirtualArray.
StringSet vpoolVarrays = vpool.getVirtualArrays();
if ((vpoolVarrays != null) && (!vpoolVarrays.contains(varrayId))) {
String message = String.format("Virtual Array %s is not assigned to Virtual Pool %s. ", varray.forDisplay(), vpool.forDisplay());
errorMessage.append(message);
_log.error(message);
if (optionalAttributes != null) {
optionalAttributes.put(AttributeMatcher.ERROR_MESSAGE, errorMessage);
}
return storagePools;
}
// Get pools for VirtualPool and VirtualArray
List<StoragePool> matchedPoolsForCos = VirtualPool.getValidStoragePools(vpool, _dbClient, true);
if (matchedPoolsForCos.isEmpty()) {
_log.warn("vPool {} does not have any valid storage pool in vArray {}.", vpool.getId(), varray.getId());
throw APIException.badRequests.noStoragePoolsForVpoolInVarray(varray.getLabel(), vpool.getLabel());
}
AttributeMapBuilder provMapBuilder = new ProvisioningAttributeMapBuilder(capabilities.getSize(), varrayId, capabilities.getThinVolumePreAllocateSize());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.provisioning_type.toString(), vpool.getSupportedProvisioningType());
// Set CG related attributes for placement
final BlockConsistencyGroup consistencyGroup = capabilities.getBlockConsistencyGroup() == null ? null : _dbClient.queryObject(BlockConsistencyGroup.class, capabilities.getBlockConsistencyGroup());
if (consistencyGroup != null) {
URI cgStorageSystemURI = consistencyGroup.getStorageController();
if (!NullColumnValueGetter.isNullURI(cgStorageSystemURI)) {
StorageSystem cgStorageSystem = _dbClient.queryObject(StorageSystem.class, cgStorageSystemURI);
Set<String> storageSystemSet = new HashSet<String>();
// this logic is added, as we don't want to add any relationships between source and target CGs explicitly in ViPR.
if (VirtualPoolCapabilityValuesWrapper.SRDF_TARGET.equalsIgnoreCase(capabilities.getPersonality())) {
// then update storage system corresponding to target CG
// source Label is set as alternate name for target Cgs, so that the same name can be used to create targte CGs in
// Array.
List<URI> cgUris = _dbClient.queryByConstraint(AlternateIdConstraint.Factory.getBlockConsistencyGroupByAlternateNameConstraint(consistencyGroup.getLabel()));
if (!cgUris.isEmpty()) {
BlockConsistencyGroup targetCgGroup = _dbClient.queryObject(BlockConsistencyGroup.class, cgUris.get(0));
if (null != targetCgGroup && !targetCgGroup.getInactive() && null != targetCgGroup.getStorageController() && !NullColumnValueGetter.isNullURI(targetCgGroup.getStorageController())) {
storageSystemSet.add(targetCgGroup.getStorageController().toString());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
}
}
} else if (!DiscoveredDataObject.Type.vplex.name().equals(cgStorageSystem.getSystemType())) {
// If this is not a VPLEX CG, add the ConsistencyGroup's StorageSystem
// so that the matching pools are in the same system
storageSystemSet.add(cgStorageSystemURI.toString());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
// IBM XIV requires all volumes of a CG in the same StoragePool
if (DiscoveredDataObject.Type.ibmxiv.name().equals(cgStorageSystem.getSystemType())) {
List<Volume> activeCGVolumes = CustomQueryUtility.queryActiveResourcesByConstraint(_dbClient, Volume.class, AlternateIdConstraint.Factory.getBlockObjectsByConsistencyGroup(consistencyGroup.getId().toString()));
if (!activeCGVolumes.isEmpty()) {
URI cgPoolURI = activeCGVolumes.get(0).getPool();
if (!NullColumnValueGetter.isNullURI(cgPoolURI)) {
Iterator<StoragePool> itr = matchedPoolsForCos.iterator();
while (itr.hasNext()) {
// remove all pools from matchedPoolsForCos except the one matched
URI poolURI = itr.next().getId();
if (!cgPoolURI.equals(poolURI)) {
_log.debug("Remove pool {} from list", poolURI);
itr.remove();
}
}
}
if (!matchedPoolsForCos.isEmpty()) {
_log.debug("Pool {} is used by CG {}", cgPoolURI, consistencyGroup.getId());
} else {
_log.warn("vPool {} does not have required IBM XIV storage pool in vArray {}.", vpool.getId(), varray.getId());
throw APIException.badRequests.noStoragePoolsForVpoolInVarray(varray.getLabel(), vpool.getLabel());
}
}
}
} else {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
}
} else {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.multi_volume_consistency.name(), true);
}
}
// This is used by the VPLEX to control consistency groups.
if (capabilities.getSourceStorageDevice() != null) {
StorageSystem sourceStorageSystem = capabilities.getSourceStorageDevice();
Set<String> storageSystemSet = new HashSet<String>();
storageSystemSet.add(sourceStorageSystem.getId().toString());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
} else if (capabilities.getExcludedStorageDevice() != null) {
StorageSystem excludedStorageSystem = capabilities.getExcludedStorageDevice();
Set<String> storageSystemSet = new HashSet<String>();
storageSystemSet.add(excludedStorageSystem.getId().toString());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.exclude_storage_system.name(), storageSystemSet);
}
// populate DriveType,and Raid level and Policy Name for FAST Initial Placement Selection
provMapBuilder.putAttributeInMap(Attributes.auto_tiering_policy_name.toString(), vpool.getAutoTierPolicyName());
provMapBuilder.putAttributeInMap(Attributes.unique_policy_names.toString(), vpool.getUniquePolicyNames());
provMapBuilder.putAttributeInMap(AttributeMatcher.PLACEMENT_MATCHERS, true);
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.drive_type.name(), vpool.getDriveType());
StringSetMap arrayInfo = vpool.getArrayInfo();
if (null != arrayInfo) {
Set<String> raidLevels = arrayInfo.get(VirtualPoolCapabilityValuesWrapper.RAID_LEVEL);
if (null != raidLevels && !raidLevels.isEmpty()) {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.raid_levels.name(), raidLevels);
}
Set<String> systemTypes = arrayInfo.get(AttributeMatcher.Attributes.system_type.name());
if (null != systemTypes && !systemTypes.isEmpty()) {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.system_type.name(), systemTypes);
// put quota value for ecs storage
if (systemTypes.contains("ecs") && capabilities.getQuota() != null) {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.quota.name(), capabilities.getQuota());
}
}
}
Map<URI, VpoolRemoteCopyProtectionSettings> remoteProtectionSettings = vpool.getRemoteProtectionSettings(vpool, _dbClient);
if (null != remoteProtectionSettings && !remoteProtectionSettings.isEmpty()) {
provMapBuilder.putAttributeInMap(Attributes.remote_copy.toString(), VirtualPool.groupRemoteCopyModesByVPool(vpool.getId(), remoteProtectionSettings));
}
if (VirtualPoolCapabilityValuesWrapper.FILE_REPLICATION_SOURCE.equalsIgnoreCase(capabilities.getPersonality())) {
// Run the placement algorithm for file replication!!!
if (capabilities.getFileReplicationType() != null && !FileReplicationType.NONE.name().equalsIgnoreCase(capabilities.getFileReplicationType())) {
provMapBuilder.putAttributeInMap(Attributes.file_replication_type.toString(), capabilities.getFileReplicationType());
if (capabilities.getFileRpCopyMode() != null) {
provMapBuilder.putAttributeInMap(Attributes.file_replication_copy_mode.toString(), capabilities.getFileRpCopyMode());
}
if (capabilities.getFileReplicationTargetVArrays() != null) {
provMapBuilder.putAttributeInMap(Attributes.file_replication_target_varray.toString(), capabilities.getFileReplicationTargetVArrays());
}
if (capabilities.getFileReplicationTargetVPool() != null) {
provMapBuilder.putAttributeInMap(Attributes.file_replication_target_vpool.toString(), capabilities.getFileReplicationTargetVPool());
}
}
}
if (capabilities.getSupportsSoftLimit()) {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.support_soft_limit.name(), capabilities.getSupportsSoftLimit());
}
if (capabilities.getSupportsNotificationLimit()) {
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.support_notification_limit.name(), capabilities.getSupportsNotificationLimit());
}
if (!(VirtualPool.vPoolSpecifiesProtection(vpool) || VirtualPool.vPoolSpecifiesSRDF(vpool) || VirtualPool.vPoolSpecifiesHighAvailability(vpool) || VirtualPool.vPoolSpecifiesHighAvailabilityDistributed(vpool))) {
// only enforce array affinity policy for vpool without RP, SRDF, VPLEX
boolean arrayAffinity = VirtualPool.ResourcePlacementPolicyType.array_affinity.name().equals(vpool.getPlacementPolicy());
if (arrayAffinity && capabilities.getCompute() != null) {
capabilities.put(VirtualPoolCapabilityValuesWrapper.ARRAY_AFFINITY, true);
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.array_affinity.name(), true);
}
}
URI portGroupURI = capabilities.getPortGroup();
boolean usePortGroup = !NullColumnValueGetter.isNullURI(portGroupURI);
if (usePortGroup) {
if (!VirtualPool.vPoolSpecifiesHighAvailability(vpool)) {
StoragePortGroup portGroup = _dbClient.queryObject(StoragePortGroup.class, portGroupURI);
URI pgSystemURI = portGroup.getStorageDevice();
boolean setSystemMatcher = true;
if (consistencyGroup != null) {
URI cgSystemURI = consistencyGroup.getStorageController();
if (!NullColumnValueGetter.isNullURI(cgSystemURI)) {
if (!cgSystemURI.equals(pgSystemURI)) {
// consistency group and port group does not belong to the same storage system
throw APIException.badRequests.cgPortGroupNotMatch(portGroupURI.toString(), consistencyGroup.getId().toString());
} else {
// system matcher has been set
setSystemMatcher = false;
}
}
}
if (setSystemMatcher) {
Set<String> storageSystemSet = new HashSet<String>();
storageSystemSet.add(pgSystemURI.toString());
provMapBuilder.putAttributeInMap(AttributeMatcher.Attributes.storage_system.name(), storageSystemSet);
}
} else {
// port group could be only specified for native vmax
throw APIException.badRequests.portGroupValidForVMAXOnly();
}
} else {
// PG was not supplied. This is normally OK unless the VMAX PG feature in enabled and the vpool is not for VPLEX.
String value = _customConfigHandler.getComputedCustomConfigValue(CustomConfigConstants.VMAX_USE_PORT_GROUP_ENABLED, Type.vmax.name(), null);
if (Boolean.TRUE.toString().equalsIgnoreCase(value) && !VirtualPool.vPoolSpecifiesHighAvailability(vpool)) {
// VMAX PG feature is enabled. Limit the valid storage pools to those not requiring PG.
limitToStoragePoolsNotRequiringPortGroup(capabilities, vpool, provMapBuilder);
}
}
Map<String, Object> attributeMap = provMapBuilder.buildMap();
if (optionalAttributes != null) {
attributeMap.putAll(optionalAttributes);
}
_log.info("Populated attribute map: {}", attributeMap);
// Execute basic precondition check to verify that vArray has active storage pools in the vPool.
// We will return a more accurate error condition if this basic check fails.
List<StoragePool> matchedPools = _matcherFramework.matchAttributes(matchedPoolsForCos, attributeMap, _dbClient, _coordinator, AttributeMatcher.BASIC_PLACEMENT_MATCHERS, errorMessage);
if (matchedPools == null || matchedPools.isEmpty()) {
_log.warn("vPool {} does not have active storage pools in vArray {} .", vpool.getId(), varray.getId());
throw APIException.badRequests.noStoragePools(varray.getLabel(), vpool.getLabel(), errorMessage.toString());
}
errorMessage.setLength(0);
// Matches the pools against the VolumeParams.
// Use a set of matched pools returned from the basic placement matching as the input for this call.
matchedPools = _matcherFramework.matchAttributes(matchedPools, attributeMap, _dbClient, _coordinator, AttributeMatcher.PLACEMENT_MATCHERS, errorMessage);
if (matchedPools == null || matchedPools.isEmpty()) {
if (optionalAttributes != null) {
optionalAttributes.put(AttributeMatcher.ERROR_MESSAGE, errorMessage);
}
_log.warn("Varray {} does not have storage pools which match vpool {} properties and have specified capabilities.", varray.getId(), vpool.getId());
return storagePools;
}
storagePools.addAll(matchedPools);
return storagePools;
}
Aggregations